Commit 8f9cf685 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-02-05

# Conflicts:
#	app/assets/javascripts/dispatcher.js
#	app/assets/javascripts/main.js
#	app/assets/stylesheets/framework.scss
#	app/controllers/application_controller.rb
#	app/helpers/projects_helper.rb
#	app/models/note.rb
#	app/models/protected_branch.rb
#	app/services/ci/register_job_service.rb
#	app/services/users/build_service.rb
#	app/views/admin/health_check/show.html.haml
#	app/views/ci/variables/_variable_row.html.haml
#	app/views/help/index.html.haml
#	app/views/layouts/devise.html.haml
#	app/views/layouts/nav/sidebar/_profile.html.haml
#	lib/api/helpers/runner.rb
#	lib/gitlab/auth.rb
#	spec/lib/gitlab/current_settings_spec.rb
#	spec/lib/gitlab/usage_data_spec.rb

[ci skip]
parents 1f577b6a 9f553730
......@@ -51,6 +51,9 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
## Contribute to GitLab
For a first-time step-by-step guide to the contribution process, see
["Contributing to GitLab"](https://about.gitlab.com/contributing/).
Thank you for your interest in contributing to GitLab. This guide details how
to contribute to GitLab in a way that is efficient for everyone.
......
......@@ -235,7 +235,7 @@ export default class FileTemplateMediator {
}
setFilename(name) {
this.$filenameInput.val(name);
this.$filenameInput.val(name).trigger('change');
}
getSelected() {
......
......@@ -12,6 +12,7 @@ import ShortcutsIssuable from './shortcuts_issuable';
import Diff from './diff';
import SearchAutocomplete from './search_autocomplete';
<<<<<<< HEAD
// EE-only
import UsersSelect from './users_select';
import UserCallout from './user_callout';
......@@ -22,6 +23,8 @@ import initPathLocks from 'ee/path_locks'; // eslint-disable-line import/first
import initApprovals from 'ee/approvals'; // eslint-disable-line import/first
import initLDAPGroupsSelect from 'ee/ldap_groups_select'; // eslint-disable-line import/first
=======
>>>>>>> upstream/master
var Dispatcher;
(function() {
......
......@@ -461,7 +461,7 @@ class GfmAutoComplete {
const accentAChar = decodeURI('%C3%80');
const accentYChar = decodeURI('%C3%BF');
const regexp = new RegExp(`^(?:\\B|[^a-zA-Z0-9_${atSymbolsWithoutBar}]|\\s)${resultantFlag}(?!${atSymbolsWithBar})((?:[A-Za-z${accentAChar}-${accentYChar}0-9_'.+-]|[^\\x00-\\x7a])*)$`, 'gi');
const regexp = new RegExp(`^(?:\\B|[^a-zA-Z0-9_\`${atSymbolsWithoutBar}]|\\s)${resultantFlag}(?!${atSymbolsWithBar})((?:[A-Za-z${accentAChar}-${accentYChar}0-9_'.+-]|[^\\x00-\\x7a])*)$`, 'gi');
return regexp.exec(targetSubtext);
}
......
......@@ -33,9 +33,12 @@ import './projects_dropdown';
import './render_gfm';
import initBreadcrumbs from './breadcrumb';
<<<<<<< HEAD
// EE-only scripts
import 'ee/main';
=======
>>>>>>> upstream/master
import initDispatcher from './dispatcher';
// eslint-disable-next-line global-require, import/no-commonjs
......
......@@ -59,5 +59,8 @@
@import "framework/memory_graph";
@import "framework/responsive_tables";
@import "framework/stacked-progress-bar";
<<<<<<< HEAD
@import "framework/sortable";
=======
>>>>>>> upstream/master
@import "framework/ci_variable_list";
......@@ -16,3 +16,31 @@
background-color: $user-mention-bg-hover;
}
}
.gfm-color_chip {
display: inline-block;
margin: 0 0 2px 4px;
vertical-align: middle;
border-radius: 3px;
$chip-size: 0.9em;
$bg-size: $chip-size / 0.9;
$bg-pos: $bg-size / 2;
width: $chip-size;
height: $chip-size;
background: $white-light;
background-image: linear-gradient(135deg, $gray-dark 25%, transparent 0%, transparent 75%, $gray-dark 0%),
linear-gradient(135deg, $gray-dark 25%, transparent 0%, transparent 75%, $gray-dark 0%);
background-size: $bg-size $bg-size;
background-position: 0 0, $bg-pos $bg-pos;
> span {
display: inline-block;
width: 100%;
height: 100%;
margin-bottom: 2px;
border-radius: 3px;
border: 1px solid $black-transparent;
}
}
......@@ -123,11 +123,15 @@ class ApplicationController < ActionController::Base
end
def after_sign_out_path_for(resource)
<<<<<<< HEAD
if Gitlab::Geo.secondary?
Gitlab::Geo.primary_node.oauth_logout_url(@geo_logout_state)
else
Gitlab::CurrentSettings.after_sign_out_path.presence || new_user_session_path
end
=======
Gitlab::CurrentSettings.after_sign_out_path.presence || new_user_session_path
>>>>>>> upstream/master
end
def can?(object, action, subject = :global)
......
module ProjectsHelper
<<<<<<< HEAD
prepend ::EE::ProjectsHelper
=======
>>>>>>> upstream/master
def link_to_project(project)
link_to [project.namespace.becomes(Namespace), project], title: h(project.name) do
title = content_tag(:span, project.name, class: 'project-name')
......
......@@ -36,9 +36,8 @@ class Key < ActiveRecord::Base
after_destroy :refresh_user_cache
def key=(value)
value&.delete!("\n\r")
value.strip! unless value.blank?
write_attribute(:key, value)
write_attribute(:key, value.present? ? Gitlab::SSHPublicKey.sanitize(value) : nil)
@public_key = nil
end
......@@ -100,7 +99,7 @@ class Key < ActiveRecord::Base
def generate_fingerprint
self.fingerprint = nil
return unless self.key.present?
return unless public_key.valid?
self.fingerprint = public_key.fingerprint
end
......
......@@ -3,8 +3,11 @@
# A note of this type is never resolvable.
class Note < ActiveRecord::Base
extend ActiveModel::Naming
<<<<<<< HEAD
prepend EE::Note
=======
>>>>>>> upstream/master
include Participable
include Mentionable
include Elastic::NotesSearch
......
class ProtectedBranch < ActiveRecord::Base
include Gitlab::ShellAdapter
include ProtectedRef
<<<<<<< HEAD
prepend EE::ProtectedRef
=======
>>>>>>> upstream/master
protected_ref_access_levels :merge, :push
......
......@@ -180,15 +180,7 @@ class Repository
end
def find_branch(name, fresh_repo: true)
# Since the Repository object may have in-memory index changes, invalidating the memoized Repository object may
# cause unintended side effects. Because finding a branch is a read-only operation, we can safely instantiate
# a new repo here to ensure a consistent state to avoid a libgit2 bug where concurrent access (e.g. via git gc)
# may cause the branch to "disappear" erroneously or have the wrong SHA.
#
# See: https://github.com/libgit2/libgit2/issues/1534 and https://gitlab.com/gitlab-org/gitlab-ce/issues/15392
raw_repo = fresh_repo ? initialize_raw_repository : raw_repository
raw_repo.find_branch(name)
raw_repository.find_branch(name, fresh_repo)
end
def find_tag(name)
......@@ -728,11 +720,11 @@ class Repository
end
def branch_names_contains(sha)
refs_contains_sha('branch', sha)
raw_repository.branch_names_contains_sha(sha)
end
def tag_names_contains(sha)
refs_contains_sha('tag', sha)
raw_repository.tag_names_contains_sha(sha)
end
def local_branches
......
......@@ -2,8 +2,11 @@ module Ci
# This class responsible for assigning
# proper pending build to runner on runner API request
class RegisterJobService
<<<<<<< HEAD
prepend EE::Ci::RegisterJobService
=======
>>>>>>> upstream/master
attr_reader :runner
Result = Struct.new(:build, :valid?)
......
module Users
class BuildService < BaseService
<<<<<<< HEAD
prepend ::EE::Users::BuildService
=======
>>>>>>> upstream/master
def initialize(current_user, params = {})
@current_user = current_user
@params = params.dup
......
......@@ -23,9 +23,13 @@
%code= liveness_url(token: Gitlab::CurrentSettings.health_check_access_token)
%li
%code= metrics_url(token: Gitlab::CurrentSettings.health_check_access_token)
<<<<<<< HEAD
- if Gitlab::Geo.secondary?
%li
%code= health_check_url(token: Gitlab::CurrentSettings.health_check_access_token, checks: :geo)
=======
>>>>>>> upstream/master
%hr
.panel.panel-default
.panel-heading
......
......@@ -44,7 +44,10 @@
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
= sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
-# EE-specific start
<<<<<<< HEAD
= render 'ci/variables/environment_scope', form_field: form_field, variable: variable
=======
>>>>>>> upstream/master
-# EE-specific end
%button.js-row-remove-button.ci-variable-row-remove-button{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
= icon('minus-circle')
......@@ -2,7 +2,11 @@
%div
- if Gitlab::CurrentSettings.help_page_text.present?
<<<<<<< HEAD
= markdown(Gitlab::CurrentSettings.help_page_text)
=======
= markdown_field(Gitlab::CurrentSettings.current_application_settings, :help_page_text)
>>>>>>> upstream/master
%hr
%h1
......
......@@ -28,11 +28,14 @@
- if Gitlab::CurrentSettings.sign_in_text.present?
= markdown_field(Gitlab::CurrentSettings.current_application_settings, :sign_in_text)
<<<<<<< HEAD
- if Gitlab::CurrentSettings.help_text.present?
%h3 Need help?
%hr
%p.slead
= markdown(Gitlab::CurrentSettings.help_text)
=======
>>>>>>> upstream/master
%hr.footer-fixed
.container.footer-container
......
......@@ -28,6 +28,7 @@
= link_to profile_account_path do
%strong.fly-out-top-item-name
#{ _('Account') }
<<<<<<< HEAD
- if Gitlab::CurrentSettings.should_check_namespace_plan?
= nav_link(controller: :billings) do
= link_to profile_billings_path do
......@@ -40,6 +41,8 @@
= link_to profile_billings_path do
%strong.fly-out-top-item-name
#{ _('Billing') }
=======
>>>>>>> upstream/master
- if Gitlab::CurrentSettings.user_oauth_applications?
= nav_link(controller: 'oauth/applications') do
= link_to applications_profile_path do
......
---
title: Add Colors to GitLab Flavored Markdown
merge_request: 16095
author: Tony Rom <thetonyrom@gmail.com>
type: added
---
title: Show coverage to two decimal points in coverage badge
merge_request: 10083
author: Jeff Stubler
type: changed
---
title: Sanitize extra blank spaces used when uploading a SSH key
merge_request: 40552
author:
type: fixed
---
title: Fix forking projects when no restricted visibility levels are defined applicationwide
merge_request: 16881
author:
type: fixed
---
title: Trigger change event on filename input when file template is applied
merge_request: 16911
author: Sebastian Klingler
type: fixed
# Copy of 20180202111106 - this one should run before 20171207150343 to fix issues related to
# the removal of groups with labels.
class RemoveProjectLabelsGroupIdCopy < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
# rubocop:disable Migration/UpdateColumnInBatches
update_column_in_batches(:labels, :group_id, nil) do |table, query|
query.where(table[:type].eq('ProjectLabel').and(table[:group_id].not_eq(nil)))
end
# rubocop:enable Migration/UpdateColumnInBatches
end
def down
end
end
......@@ -13,7 +13,7 @@ override certain values.
Variable | Type | Description
-------- | ---- | -----------
`GITLAB_CDN_HOST` | string | Sets the hostname for a CDN to serve static assets (e.g. `mycdnsubdomain.fictional-cdn.com`)
`GITLAB_CDN_HOST` | string | Sets the base URL for a CDN to serve static assets (e.g. `//mycdnsubdomain.fictional-cdn.com`)
`GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation
`GITLAB_HOST` | string | The full URL of the GitLab server (including `http://` or `https://`)
`RAILS_ENV` | string | The Rails environment; can be one of `production`, `development`, `staging` or `test`
......
......@@ -254,7 +254,7 @@ GFM will recognize the following:
| `@user_name` | specific user |
| `@group_name` | specific group |
| `@all` | entire team |
| `#123` | issue |
| `#12345` | issue |
| `!123` | merge request |
| `$123` | snippet |
| `&123` | epic |
......@@ -382,6 +382,45 @@ _Be advised that KaTeX only supports a [subset][katex-subset] of LaTeX._
>**Note:**
This also works for the asciidoctor `:stem: latexmath`. For details see the [asciidoctor user manual][asciidoctor-manual].
### Colors
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#colors
It is possible to have color written in HEX, RGB or HSL format rendered with a color indicator.
Color written inside backticks will be followed by a color "chip".
Examples:
`#F00`
`#F00A`
`#FF0000`
`#FF0000AA`
`RGB(0,255,0)`
`RGB(0%,100%,0%)`
`RGBA(0,255,0,0.7)`
`HSL(540,70%,50%)`
`HSLA(540,70%,50%,0.7)`
Becomes:
`#F00`
`#F00A`
`#FF0000`
`#FF0000AA`
`RGB(0,255,0)`
`RGB(0%,100%,0%)`
`RGBA(0,255,0,0.7)`
`HSL(540,70%,50%)`
`HSLA(540,70%,50%,0.7)`
#### Supported formats:
* HEX: `` `#RGB[A]` `` or `` `#RRGGBB[AA]` ``
* RGB: `` `RGB[A](R, G, B[, A])` ``
* HSL: `` `HSL[A](H, S, L[, A])` ``
### Mermaid
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15107) in
......
......@@ -46,7 +46,7 @@ namespace that started the import process.
The importer will also import branches on forks of projects related to open pull
requests. These branches will be imported with a naming scheme similar to
GH-SHA-Username/Pull-Request-number/fork-name/branch. This may lead to a discrepency
GH-SHA-Username/Pull-Request-number/fork-name/branch. This may lead to a discrepancy
in branches compared to the GitHub Repository.
For a more technical description and an overview of the architecture you can
......
module API
module Helpers
module Runner
<<<<<<< HEAD
prepend EE::API::Helpers::Runner
=======
>>>>>>> upstream/master
JOB_TOKEN_HEADER = 'HTTP_JOB_TOKEN'.freeze
JOB_TOKEN_PARAM = :token
UPDATE_RUNNER_EVERY = 10 * 60
......
module Banzai
module ColorParser
ALPHA = /0(?:\.\d+)?|\.\d+|1(?:\.0+)?/ # 0.0..1.0
PERCENTS = /(?:\d{1,2}|100)%/ # 00%..100%
ALPHA_CHANNEL = /(?:,\s*(?:#{ALPHA}|#{PERCENTS}))?/
BITS = /\d{1,2}|1\d\d|2(?:[0-4]\d|5[0-5])/ # 00..255
DEGS = /-?\d+(?:deg)?/i # [-]digits[deg]
RADS = /-?(?:\d+(?:\.\d+)?|\.\d+)rad/i # [-](digits[.digits] OR .digits)rad
HEX_FORMAT = /\#(?:\h{3}|\h{4}|\h{6}|\h{8})/
RGB_FORMAT = %r{
(?:rgba?
\(
(?:
(?:(?:#{BITS},\s*){2}#{BITS})
|
(?:(?:#{PERCENTS},\s*){2}#{PERCENTS})
)
#{ALPHA_CHANNEL}
\)
)
}xi
HSL_FORMAT = %r{
(?:hsla?
\(
(?:#{DEGS}|#{RADS}),\s*#{PERCENTS},\s*#{PERCENTS}
#{ALPHA_CHANNEL}
\)
)
}xi
FORMATS = [HEX_FORMAT, RGB_FORMAT, HSL_FORMAT].freeze
COLOR_FORMAT = /\A(#{Regexp.union(FORMATS)})\z/ix
# Public: Analyzes whether the String is a color code.
#
# text - The String to be parsed.
#
# Returns the recognized color String or nil if none was found.
def self.parse(text)
text if COLOR_FORMAT =~ text
end
end
end
module Banzai
module Filter
# HTML filter that renders `color` followed by a color "chip".
#
class ColorFilter < HTML::Pipeline::Filter
COLOR_CHIP_CLASS = 'gfm-color_chip'.freeze
def call
doc.css('code').each do |node|
color = ColorParser.parse(node.content)
node << color_chip(color) if color
end
doc
end
private
def color_chip(color)
checkerboard = doc.document.create_element('span', class: COLOR_CHIP_CLASS)
chip = doc.document.create_element('span', style: inline_styles(color: color))
checkerboard << chip
end
def inline_styles(color:)
"background-color: #{color};"
end
end
end
end
......@@ -7,6 +7,7 @@ module Banzai
Filter::SanitizationFilter,
Filter::EmojiFilter,
Filter::ColorFilter,
Filter::AutolinkFilter,
Filter::ExternalLinkFilter
]
......
......@@ -14,6 +14,7 @@ module Banzai
Filter::SyntaxHighlightFilter,
Filter::MathFilter,
Filter::ColorFilter,
Filter::MermaidFilter,
Filter::VideoLinkFilter,
Filter::ImageLazyLoadFilter,
......
......@@ -14,8 +14,11 @@ module Gitlab
DEFAULT_SCOPES = [:api].freeze
class << self
<<<<<<< HEAD
prepend EE::Gitlab::Auth
=======
>>>>>>> upstream/master
def find_for_git_client(login, password, project:, ip:)
raise "Must provide an IP for rate limiting" if ip.nil?
......
......@@ -23,7 +23,7 @@ module Gitlab
@coverage ||= raw_coverage
return unless @coverage
@coverage.to_i
@coverage.to_f.round(2)
end
def metadata
......
......@@ -25,7 +25,7 @@ module Gitlab
end
def value_text
@status ? "#{@status}%" : 'unknown'
@status ? ("%.2f%%" % @status) : 'unknown'
end
def key_width
......@@ -33,7 +33,7 @@ module Gitlab
end
def value_width
@status ? 36 : 58
@status ? 54 : 58
end
def value_color
......
# Gitaly note: JV: no RPC's here.
module Gitlab
module Git
class Branch < Ref
......
......@@ -1363,20 +1363,23 @@ module Gitlab
raise CommandError.new(e)
end
def refs_contains_sha(ref_type, sha)
args = %W(#{ref_type} --contains #{sha})
names = run_git(args).first
if names.respond_to?(:split)
names = names.split("\n").map(&:strip)
names.each do |name|
name.slice! '* '
def branch_names_contains_sha(sha)
gitaly_migrate(:branch_names_contains_sha) do |is_enabled|
if is_enabled
gitaly_ref_client.branch_names_contains_sha(sha)
else
refs_contains_sha(:branch, sha)
end
end
end
names
else
[]
def tag_names_contains_sha(sha)
gitaly_migrate(:tag_names_contains_sha) do |is_enabled|
if is_enabled
gitaly_ref_client.tag_names_contains_sha(sha)
else
refs_contains_sha(:tag, sha)
end
end
end
......@@ -1454,6 +1457,21 @@ module Gitlab
end
end
def refs_contains_sha(ref_type, sha)
args = %W(#{ref_type} --contains #{sha})
names = run_git(args).first
return [] unless names.respond_to?(:split)
names = names.split("\n").map(&:strip)
names.each do |name|
name.slice! '* '
end
names
end
def rugged_write_config(full_path:)
rugged.config['gitlab.fullpath'] = full_path
end
......
# Gitaly note: JV: no RPC's here.
#
module Gitlab
module Git
class Tag < Ref
......
......@@ -145,6 +145,32 @@ module Gitlab
raise Gitlab::Git::Repository::GitError, response.git_error if response.git_error.present?
end
# Limit: 0 implies no limit, thus all tag names will be returned
def tag_names_contains_sha(sha, limit: 0)
request = Gitaly::ListTagNamesContainingCommitRequest.new(
repository: @gitaly_repo,
commit_id: sha,
limit: limit
)
stream = GitalyClient.call(@repository.storage, :ref_service, :list_tag_names_containing_commit, request)
consume_ref_contains_sha_response(stream, :tag_names)
end
# Limit: 0 implies no limit, thus all tag names will be returned
def branch_names_contains_sha(sha, limit: 0)
request = Gitaly::ListBranchNamesContainingCommitRequest.new(
repository: @gitaly_repo,
commit_id: sha,
limit: limit
)
stream = GitalyClient.call(@repository.storage, :ref_service, :list_branch_names_containing_commit, request)
consume_ref_contains_sha_response(stream, :branch_names)
end
private
def consume_refs_response(response)
......@@ -215,6 +241,13 @@ module Gitlab
Gitlab::Git::Commit.decorate(@repository, hash)
end
def consume_ref_contains_sha_response(stream, collection_name)
stream.each_with_object([]) do |response, array|
encoded_names = response.send(collection_name).map { |b| Gitlab::Git.ref_name(b) } # rubocop:disable GitlabSecurity/PublicSend
array.concat(encoded_names)
end
end
def invalid_ref!(message)
raise Gitlab::Git::Repository::InvalidRef.new(message)
end
......
......@@ -21,6 +21,22 @@ module Gitlab
technology(name)&.supported_sizes
end
def self.sanitize(key_content)
ssh_type, *parts = key_content.strip.split
return key_content if parts.empty?
parts.each_with_object("#{ssh_type} ").with_index do |(part, content), index|
content << part
if Gitlab::SSHPublicKey.new(content).valid?
break [content, parts[index + 1]].compact.join(' ') # Add the comment part if present
elsif parts.size == index + 1 # return original content if we've reached the last element
break key_content
end
end
end
attr_reader :key_text, :key
# Unqualified MD5 fingerprint for compatibility
......@@ -37,23 +53,23 @@ module Gitlab
end
def valid?
key.present?
key.present? && bits && technology.supported_sizes.include?(bits)
end
def type
technology.name if valid?
technology.name if key.present?
end
def bits
return unless valid?
return if key.blank?
case type
when :rsa
key.n.num_bits
key.n&.num_bits
when :dsa
key.p.num_bits
key.p&.num_bits
when :ecdsa
key.group.order.num_bits
key.group.order&.num_bits
when :ed25519
256
else
......
......@@ -59,7 +59,7 @@ module Gitlab
def allowed_levels
restricted_levels = Gitlab::CurrentSettings.restricted_visibility_levels
self.values - restricted_levels
self.values - Array(restricted_levels)
end
def closest_allowed_level(target_level)
......
......@@ -5,6 +5,10 @@ FactoryBot.define do
title
key { Spec::Support::Helpers::KeyGeneratorHelper.new(1024).generate + ' dummy@gitlab.com' }
factory :key_without_comment do
key { Spec::Support::Helpers::KeyGeneratorHelper.new(1024).generate }
end
factory :deploy_key, class: 'DeployKey'
factory :personal_key do
......
......@@ -261,6 +261,10 @@ describe 'GitLab Markdown' do
it 'includes VideoLinkFilter' do
expect(doc).to parse_video_links
end
it 'includes ColorFilter' do
expect(doc).to parse_colors
end
end
context 'wiki pipeline' do
......@@ -323,6 +327,10 @@ describe 'GitLab Markdown' do
it 'includes VideoLinkFilter' do
expect(doc).to parse_video_links
end
it 'includes ColorFilter' do
expect(doc).to parse_colors
end
end
# Fake a `current_user` helper
......
......@@ -18,7 +18,7 @@ feature 'test coverage badge' do
show_test_coverage_badge
expect_coverage_badge('95%')
expect_coverage_badge('95.00%')
end
scenario 'user requests coverage badge for specific job' do
......@@ -30,7 +30,7 @@ feature 'test coverage badge' do
show_test_coverage_badge(job: 'coverage')
expect_coverage_badge('85%')
expect_coverage_badge('85.00%')
end
scenario 'user requests coverage badge for pipeline without coverage' do
......
......@@ -288,6 +288,18 @@ However the wrapping tags cannot be mixed as such:
![My Video](/assets/videos/gitlab-demo.mp4)
### Colors
`#F00`
`#F00A`
`#FF0000`
`#FF0000AA`
`RGB(0,255,0)`
`RGB(0%,100%,0%)`
`RGBA(0,255,0,0.7)`
`HSL(540,70%,50%)`
`HSLA(540,70%,50%,0.7)`
### Mermaid
> If this is not rendered correctly, see
......
......@@ -130,16 +130,25 @@ describe('GfmAutoComplete', function () {
});
describe('should not match special sequences', () => {
const ShouldNotBeFollowedBy = flags.concat(['\x00', '\x10', '\x3f', '\n', ' ']);
const shouldNotBeFollowedBy = flags.concat(['\x00', '\x10', '\x3f', '\n', ' ']);
const shouldNotBePrependedBy = ['`'];
flagsUseDefaultMatcher.forEach((atSign) => {
ShouldNotBeFollowedBy.forEach((followedSymbol) => {
shouldNotBeFollowedBy.forEach((followedSymbol) => {
const seq = atSign + followedSymbol;
it(`should not match "${seq}"`, () => {
expect(defaultMatcher(atwhoInstance, atSign, seq)).toBe(null);
});
});
shouldNotBePrependedBy.forEach((prependedSymbol) => {
const seq = prependedSymbol + atSign;
it(`should not match "${seq}"`, () => {
expect(defaultMatcher(atwhoInstance, atSign, seq)).toBe(null);
});
});
});
});
});
......
require 'spec_helper'
describe Banzai::ColorParser do
describe '.parse' do
context 'HEX format' do
[
'#abc', '#ABC',
'#d2d2d2', '#D2D2D2',
'#123a', '#123A',
'#123456aa', '#123456AA'
].each do |color|
it "parses the valid hex color #{color}" do
expect(subject.parse(color)).to eq(color)
end
end
[
'#', '#1', '#12', '#12g', '#12G',
'#12345', '#r2r2r2', '#R2R2R2', '#1234567',
'# 123', '# 1234', '# 123456', '# 12345678',
'#1 2 3', '#123 4', '#12 34 56', '#123456 78'
].each do |color|
it "does not parse the invalid hex color #{color}" do
expect(subject.parse(color)).to be_nil
end
end
end
context 'RGB format' do
[
'rgb(0,0,0)', 'rgb(255,255,255)',
'rgb(0, 0, 0)', 'RGB(0,0,0)',
'rgb(0,0,0,0)', 'rgb(0,0,0,0.0)', 'rgb(0,0,0,.0)',
'rgb(0,0,0, 0)', 'rgb(0,0,0, 0.0)', 'rgb(0,0,0, .0)',
'rgb(0,0,0,1)', 'rgb(0,0,0,1.0)',
'rgba(0,0,0)', 'rgba(0,0,0,0)', 'RGBA(0,0,0)',
'rgb(0%,0%,0%)', 'rgba(0%,0%,0%,0%)'
].each do |color|
it "parses the valid rgb color #{color}" do
expect(subject.parse(color)).to eq(color)
end
end
[
'FOOrgb(0,0,0)', 'rgb(0,0,0)BAR',
'rgb(0,0,-1)', 'rgb(0,0,-0)', 'rgb(0,0,256)',
'rgb(0,0,0,-0.1)', 'rgb(0,0,0,-0.0)', 'rgb(0,0,0,-.1)',
'rgb(0,0,0,1.1)', 'rgb(0,0,0,2)',
'rgba(0,0,0,)', 'rgba(0,0,0,0.)', 'rgba(0,0,0,1.)',
'rgb(0,0,0%)', 'rgb(101%,0%,0%)'
].each do |color|
it "does not parse the invalid rgb color #{color}" do
expect(subject.parse(color)).to be_nil
end
end
end
context 'HSL format' do
[
'hsl(0,0%,0%)', 'hsl(0,100%,100%)',
'hsl(540,0%,0%)', 'hsl(-720,0%,0%)',
'hsl(0deg,0%,0%)', 'hsl(0DEG,0%,0%)',
'hsl(0, 0%, 0%)', 'HSL(0,0%,0%)',
'hsl(0,0%,0%,0)', 'hsl(0,0%,0%,0.0)', 'hsl(0,0%,0%,.0)',
'hsl(0,0%,0%, 0)', 'hsl(0,0%,0%, 0.0)', 'hsl(0,0%,0%, .0)',
'hsl(0,0%,0%,1)', 'hsl(0,0%,0%,1.0)',
'hsla(0,0%,0%)', 'hsla(0,0%,0%,0)', 'HSLA(0,0%,0%)',
'hsl(1rad,0%,0%)', 'hsl(1.1rad,0%,0%)', 'hsl(.1rad,0%,0%)',
'hsl(-1rad,0%,0%)', 'hsl(1RAD,0%,0%)'
].each do |color|
it "parses the valid hsl color #{color}" do
expect(subject.parse(color)).to eq(color)
end
end
[
'hsl(+0,0%,0%)', 'hsl(0,0,0%)', 'hsl(0,0%,0)', 'hsl(0 deg,0%,0%)',
'hsl(0,-0%,0%)', 'hsl(0,101%,0%)', 'hsl(0,-1%,0%)',
'hsl(0,0%,0%,-0.1)', 'hsl(0,0%,0%,-.1)',
'hsl(0,0%,0%,1.1)', 'hsl(0,0%,0%,2)',
'hsl(0,0%,0%,)', 'hsl(0,0%,0%,0.)', 'hsl(0,0%,0%,1.)',
'hsl(deg,0%,0%)', 'hsl(rad,0%,0%)'
].each do |color|
it "does not parse the invalid hsl color #{color}" do
expect(subject.parse(color)).to be_nil
end
end
end
end
end
require 'spec_helper'
describe Banzai::Filter::ColorFilter, lib: true do
include FilterSpecHelper
let(:color) { '#F00' }
let(:color_chip_selector) { 'code > span.gfm-color_chip > span' }
['#123', '#1234', '#123456', '#12345678',
'rgb(0,0,0)', 'RGB(0, 0, 0)', 'rgba(0,0,0,1)', 'RGBA(0,0,0,0.7)',
'hsl(270,30%,50%)', 'HSLA(270, 30%, 50%, .7)'].each do |color|
it "inserts color chip for supported color format #{color}" do
content = code_tag(color)
doc = filter(content)
color_chip = doc.at_css(color_chip_selector)
expect(color_chip.content).to be_empty
expect(color_chip.parent[:class]).to eq 'gfm-color_chip'
expect(color_chip[:style]).to eq "background-color: #{color};"
end
end
it 'ignores valid color code without backticks(code tags)' do
doc = filter(color)
expect(doc.css('span.gfm-color_chip').size).to be_zero
end
it 'ignores valid color code with prepended space' do
content = code_tag(' ' + color)
doc = filter(content)
expect(doc.css(color_chip_selector).size).to be_zero
end
it 'ignores valid color code with appended space' do
content = code_tag(color + ' ')
doc = filter(content)
expect(doc.css(color_chip_selector).size).to be_zero
end
it 'ignores valid color code surrounded by spaces' do
content = code_tag(' ' + color + ' ')
doc = filter(content)
expect(doc.css(color_chip_selector).size).to be_zero
end
it 'ignores invalid color code' do
invalid_color = '#BAR'
content = code_tag(invalid_color)
doc = filter(content)
expect(doc.css(color_chip_selector).size).to be_zero
end
def code_tag(string)
"<code>#{string}</code>"
end
end
require 'spec_helper'
describe Gitlab::Badge::Coverage::Template do
let(:badge) { double(entity: 'coverage', status: 90) }
let(:badge) { double(entity: 'coverage', status: 90.00) }
let(:template) { described_class.new(badge) }
describe '#key_text' do
......@@ -13,7 +13,17 @@ describe Gitlab::Badge::Coverage::Template do
describe '#value_text' do
context 'when coverage is known' do
it 'returns coverage percentage' do
expect(template.value_text).to eq '90%'
expect(template.value_text).to eq '90.00%'
end
end
context 'when coverage is known to many digits' do
before do
allow(badge).to receive(:status).and_return(92.349)
end
it 'returns rounded coverage percentage' do
expect(template.value_text).to eq '92.35%'
end
end
......@@ -37,7 +47,7 @@ describe Gitlab::Badge::Coverage::Template do
describe '#value_width' do
context 'when coverage is known' do
it 'is narrower when coverage is known' do
expect(template.value_width).to eq 36
expect(template.value_width).to eq 54
end
end
......@@ -113,7 +123,7 @@ describe Gitlab::Badge::Coverage::Template do
describe '#width' do
context 'when coverage is known' do
it 'returns the key width plus value width' do
expect(template.width).to eq 98
expect(template.width).to eq 116
end
end
......
......@@ -26,6 +26,7 @@ describe Gitlab::CurrentSettings do
allow(ActiveRecord::Base.connection).to receive(:active?).and_return(true)
allow(ActiveRecord::Base.connection).to receive(:table_exists?).and_call_original
allow(ActiveRecord::Base.connection).to receive(:table_exists?).with('application_settings').and_return(true)
<<<<<<< HEAD
end
# This method returns the ::ApplicationSetting.defaults hash
......@@ -34,6 +35,8 @@ describe Gitlab::CurrentSettings do
defaults = ::ApplicationSetting.defaults
ar_wrapped_defaults = ::ApplicationSetting.new(defaults).attributes
ar_wrapped_defaults.slice(*defaults.keys)
=======
>>>>>>> upstream/master
end
it 'attempts to use cached values first' do
......
......@@ -1162,14 +1162,27 @@ describe Gitlab::Git::Repository, seed_helper: true do
context 'when Gitaly find_branch feature is disabled', :skip_gitaly_mock do
it_behaves_like 'finding a branch'
it 'should reload Rugged::Repository and return master' do
expect(Rugged::Repository).to receive(:new).twice.and_call_original
context 'force_reload is true' do
it 'should reload Rugged::Repository' do
expect(Rugged::Repository).to receive(:new).twice.and_call_original
repository.find_branch('master')
branch = repository.find_branch('master', force_reload: true)
repository.find_branch('master')
branch = repository.find_branch('master', force_reload: true)
expect(branch).to be_a_kind_of(Gitlab::Git::Branch)
expect(branch.name).to eq('master')
expect(branch).to be_a_kind_of(Gitlab::Git::Branch)
expect(branch.name).to eq('master')
end
end
context 'force_reload is false' do
it 'should not reload Rugged::Repository' do
expect(Rugged::Repository).to receive(:new).once.and_call_original
branch = repository.find_branch('master', force_reload: false)
expect(branch).to be_a_kind_of(Gitlab::Git::Branch)
expect(branch.name).to eq('master')
end
end
end
end
......
......@@ -37,6 +37,41 @@ describe Gitlab::SSHPublicKey, lib: true do
end
end
describe '.sanitize(key_content)' do
let(:content) { build(:key).key }
context 'when key has blank space characters' do
it 'removes the extra blank space characters' do
unsanitized = content.insert(100, "\n")
.insert(40, "\r\n")
.insert(30, ' ')
sanitized = described_class.sanitize(unsanitized)
_, body = sanitized.split
expect(sanitized).not_to eq(unsanitized)
expect(body).not_to match(/\s/)
end
end
context "when key doesn't have blank space characters" do
it "doesn't modify the content" do
sanitized = described_class.sanitize(content)
expect(sanitized).to eq(content)
end
end
context "when key is invalid" do
it 'returns the original content' do
unsanitized = "ssh-foo any content=="
sanitized = described_class.sanitize(unsanitized)
expect(sanitized).to eq(unsanitized)
end
end
end
describe '#valid?' do
subject { public_key }
......
......@@ -156,10 +156,14 @@ describe Gitlab::UsageData do
subject { described_class.license_usage_data }
it "gathers license data" do
<<<<<<< HEAD
license = ::License.current
expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
expect(subject[:license_md5]).to eq(Digest::MD5.hexdigest(license.data))
=======
expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
>>>>>>> upstream/master
expect(subject[:version]).to eq(Gitlab::VERSION)
expect(subject[:licensee]).to eq(license.licensee)
expect(subject[:active_user_count]).to eq(User.active.count)
......
......@@ -57,6 +57,15 @@ describe Gitlab::VisibilityLevel do
expect(described_class.allowed_levels)
.to contain_exactly(described_class::PRIVATE, described_class::PUBLIC)
end
it 'returns all levels when no visibility level was set' do
allow(described_class)
.to receive_message_chain('current_application_settings.restricted_visibility_levels')
.and_return(nil)
expect(described_class.allowed_levels)
.to contain_exactly(described_class::PRIVATE, described_class::INTERNAL, described_class::PUBLIC)
end
end
describe '.closest_allowed_level' do
......
......@@ -72,16 +72,53 @@ describe Key, :mailer do
expect(build(:key)).to be_valid
end
it 'accepts a key with newline charecters after stripping them' do
key = build(:key)
key.key = key.key.insert(100, "\n")
key.key = key.key.insert(40, "\r\n")
expect(key).to be_valid
end
it 'rejects the unfingerprintable key (not a key)' do
expect(build(:key, key: 'ssh-rsa an-invalid-key==')).not_to be_valid
end
where(:factory, :chars, :expected_sections) do
[
[:key, ["\n", "\r\n"], 3],
[:key, [' ', ' '], 3],
[:key_without_comment, [' ', ' '], 2]
]
end
with_them do
let!(:key) { create(factory) }
let!(:original_fingerprint) { key.fingerprint }
it 'accepts a key with blank space characters after stripping them' do
modified_key = key.key.insert(100, chars.first).insert(40, chars.last)
_, content = modified_key.split
key.update!(key: modified_key)
expect(key).to be_valid
expect(key.key.split.size).to eq(expected_sections)
expect(content).not_to match(/\s/)
expect(original_fingerprint).to eq(key.fingerprint)
end
end
end
context 'validate size' do
where(:key_content, :result) do
[
[Spec::Support::Helpers::KeyGeneratorHelper.new(512).generate, false],
[Spec::Support::Helpers::KeyGeneratorHelper.new(8192).generate, false],
[Spec::Support::Helpers::KeyGeneratorHelper.new(1024).generate, true]
]
end
with_them do
it 'validates the size of the key' do
key = build(:key, key: key_content)
expect(key.valid?).to eq(result)
end
end
end
context 'validate it meets key restrictions' do
......
......@@ -36,26 +36,49 @@ describe Repository do
end
describe '#branch_names_contains' do
subject { repository.branch_names_contains(sample_commit.id) }
shared_examples '#branch_names_contains' do
set(:project) { create(:project, :repository) }
let(:repository) { project.repository }
it { is_expected.to include('master') }
it { is_expected.not_to include('feature') }
it { is_expected.not_to include('fix') }
subject { repository.branch_names_contains(sample_commit.id) }
describe 'when storage is broken', :broken_storage do
it 'should raise a storage error' do
expect_to_raise_storage_error do
broken_repository.branch_names_contains(sample_commit.id)
it { is_expected.to include('master') }
it { is_expected.not_to include('feature') }
it { is_expected.not_to include('fix') }
describe 'when storage is broken', :broken_storage do
it 'should raise a storage error' do
expect_to_raise_storage_error do
broken_repository.branch_names_contains(sample_commit.id)
end
end
end
end
context 'when gitaly is enabled' do
it_behaves_like '#branch_names_contains'
end
context 'when gitaly is disabled', :skip_gitaly_mock do
it_behaves_like '#branch_names_contains'
end
end
describe '#tag_names_contains' do
subject { repository.tag_names_contains(sample_commit.id) }
shared_examples '#tag_names_contains' do
subject { repository.tag_names_contains(sample_commit.id) }
it { is_expected.to include('v1.1.0') }
it { is_expected.not_to include('v1.0.0') }
it { is_expected.to include('v1.1.0') }
it { is_expected.not_to include('v1.0.0') }
end
context 'when gitaly is enabled' do
it_behaves_like '#tag_names_contains'
end
context 'when gitaly is enabled', :skip_gitaly_mock do
it_behaves_like '#tag_names_contains'
end
end
describe 'tags_sorted_by' do
......@@ -991,19 +1014,19 @@ describe Repository do
end
describe '#find_branch' do
it 'loads a branch with a fresh repo' do
expect(Gitlab::Git::Repository).to receive(:new).twice.and_call_original
context 'fresh_repo is true' do
it 'delegates the call to raw_repository' do
expect(repository.raw_repository).to receive(:find_branch).with('master', true)
2.times do
expect(repository.find_branch('feature')).not_to be_nil
repository.find_branch('master', fresh_repo: true)
end
end
it 'loads a branch with a cached repo' do
expect(Gitlab::Git::Repository).to receive(:new).once.and_call_original
context 'fresh_repo is false' do
it 'delegates the call to raw_repository' do
expect(repository.raw_repository).to receive(:find_branch).with('master', false)
2.times do
expect(repository.find_branch('feature', fresh_repo: false)).not_to be_nil
repository.find_branch('master', fresh_repo: false)
end
end
end
......
......@@ -199,6 +199,27 @@ module MarkdownMatchers
expect(video['src']).to end_with('/assets/videos/gitlab-demo.mp4')
end
end
# ColorFilter
matcher :parse_colors do
set_default_markdown_messages
match do |actual|
color_chips = actual.css('code > span.gfm-color_chip > span')
expect(color_chips.count).to eq(9)
[
'#F00', '#F00A', '#FF0000', '#FF0000AA', 'RGB(0,255,0)',
'RGB(0%,100%,0%)', 'RGBA(0,255,0,0.7)', 'HSL(540,70%,50%)',
'HSLA(540,70%,50%,0.7)'
].each_with_index do |color, i|
parsed_color = Banzai::ColorParser.parse(color)
expect(color_chips[i]['style']).to match("background-color: #{parsed_color};")
expect(color_chips[i].parent.parent.content).to match(color)
end
end
end
end
# Monkeypatch the matcher DSL so that we can reduce some noisy duplication for
......
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