Commit 3275f76c authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-08-10

# Conflicts:
#	app/assets/javascripts/reports/components/issues_list.vue
#	app/assets/javascripts/reports/components/report_issues.vue
#	app/models/project_services/hipchat_service.rb
#	app/serializers/environment_entity.rb
#	app/services/ci/enqueue_build_service.rb
#	app/views/projects/mirrors/_instructions.html.haml
#	app/views/projects/mirrors/_mirror_repos.html.haml
#	app/views/projects/mirrors/_mirror_repos_form.html.haml
#	locale/gitlab.pot

[ci skip]
parents d7318ba3 9964b678
......@@ -5,9 +5,12 @@ import {
STATUS_FAILED,
STATUS_NEUTRAL,
} from '~/reports/constants';
<<<<<<< HEAD
import { componentNames } from 'ee/vue_shared/components/reports/issue_body';
import SastContainerInfo from 'ee/vue_shared/security_reports/components/sast_container_info.vue';
=======
>>>>>>> upstream/master
/**
* Renders block of issues
......
<script>
import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
<<<<<<< HEAD
import { components, componentNames } from 'ee/vue_shared/components/reports/issue_body';
=======
import { components, componentNames } from '~/reports/components/issue_body';
>>>>>>> upstream/master
export default {
name: 'ReportIssues',
......
module MirrorHelper
def mirrors_form_data_attributes
{ project_mirror_endpoint: project_mirror_path(@project) }
end
end
......@@ -230,7 +230,7 @@ module Ci
end
def cancelable?
active?
active? || created?
end
def retryable?
......
# frozen_string_literal: true
class ProgrammingLanguage < ActiveRecord::Base
validates :name, presence: true
validates :color, allow_blank: false, color: true
......
......@@ -477,6 +477,24 @@ class Project < ActiveRecord::Base
}x
end
def reference_postfix
'>'
end
def reference_postfix_escaped
'&gt;'
end
# Pattern used to extract `namespace/project>` project references from text.
# '>' or its escaped form ('&gt;') are checked for because '>' is sometimes escaped
# when the reference comes from an external source.
def markdown_reference_pattern
%r{
#{reference_pattern}
(#{reference_postfix}|#{reference_postfix_escaped})
}x
end
def trending
joins('INNER JOIN trending_projects ON projects.id = trending_projects.project_id')
.reorder('trending_projects.id ASC')
......@@ -925,6 +943,10 @@ class Project < ActiveRecord::Base
end
end
def to_reference_with_postfix
"#{to_reference(full: true)}#{self.class.reference_postfix}"
end
# `from` argument can be a Namespace or Project.
def to_reference(from = nil, full: false)
if full || cross_namespace_reference?(from)
......
# frozen_string_literal: true
require 'asana'
class AsanaService < Service
......
# frozen_string_literal: true
class AssemblaService < Service
prop_accessor :token, :subdomain
validates :token, presence: true, if: :activated?
......
# frozen_string_literal: true
class BambooService < CiService
include ReactiveService
......
# frozen_string_literal: true
class BugzillaService < IssueTrackerService
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
......
# frozen_string_literal: true
require "addressable/uri"
class BuildkiteService < CiService
......
# frozen_string_literal: true
# This class is to be removed with 9.1
# We should also by then remove BuildsEmailService from database
class BuildsEmailService < Service
......
# frozen_string_literal: true
class CampfireService < Service
prop_accessor :token, :subdomain, :room
validates :token, presence: true, if: :activated?
......@@ -82,7 +84,7 @@ class CampfireService < Service
before = push[:before]
after = push[:after]
message = ""
message = []
message << "[#{project.full_name}] "
message << "#{push[:user_name]} "
......@@ -95,6 +97,6 @@ class CampfireService < Service
message << "#{project.web_url}/compare/#{before}...#{after}"
end
message
message.join
end
end
# frozen_string_literal: true
require 'slack-notifier'
module ChatMessage
......
# frozen_string_literal: true
module ChatMessage
class IssueMessage < BaseMessage
attr_reader :title
......
# frozen_string_literal: true
module ChatMessage
class MergeMessage < BaseMessage
attr_reader :merge_request_iid
......
# frozen_string_literal: true
module ChatMessage
class NoteMessage < BaseMessage
attr_reader :note
......
# frozen_string_literal: true
module ChatMessage
class PipelineMessage < BaseMessage
attr_reader :ref_type
......
# frozen_string_literal: true
module ChatMessage
class PushMessage < BaseMessage
attr_reader :after
......
# frozen_string_literal: true
module ChatMessage
class WikiPageMessage < BaseMessage
attr_reader :title
......
# frozen_string_literal: true
# Base class for Chat notifications services
# This class is not meant to be used directly, but only to inherit from.
class ChatNotificationService < Service
......
# frozen_string_literal: true
# Base class for CI services
# List methods you need to implement to get your CI service
# working with GitLab Merge Requests
......
# frozen_string_literal: true
class CustomIssueTrackerService < IssueTrackerService
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
......
# frozen_string_literal: true
# Base class for deployment services
#
# These services integrate with a deployment solution like Kubernetes/OpenShift,
......
# frozen_string_literal: true
class DroneCiService < CiService
include ReactiveService
......
# frozen_string_literal: true
class EmailsOnPushService < Service
boolean_accessor :send_from_committer_email
boolean_accessor :disable_diffs
......
# frozen_string_literal: true
class ExternalWikiService < Service
prop_accessor :external_wiki_url
......
# frozen_string_literal: true
require "flowdock-git-hook"
# Flow dock depends on Grit to compute the number of commits between two given
......
# frozen_string_literal: true
require "gemnasium/gitlab_service"
class GemnasiumService < Service
......
# frozen_string_literal: true
class GitlabIssueTrackerService < IssueTrackerService
include Gitlab::Routing
......
# frozen_string_literal: true
require 'hangouts_chat'
class HangoutsChatService < ChatNotificationService
......
# frozen_string_literal: true
class HipchatService < Service
include ActionView::Helpers::SanitizeHelper
......@@ -108,7 +110,7 @@ class HipchatService < Service
before = push[:before]
after = push[:after]
message = ""
message = []
message << "#{push[:user_name]} "
if Gitlab::Git.blank_ref?(before)
......@@ -132,7 +134,7 @@ class HipchatService < Service
end
end
message
message.join
end
def markdown(text, options = {})
......@@ -165,11 +167,11 @@ class HipchatService < Service
description = obj_attr[:description]
issue_link = "<a href=\"#{issue_url}\">issue ##{issue_iid}</a>"
message = "#{user_name} #{state} #{issue_link} in #{project_link}: <b>#{title}</b>"
message = ["#{user_name} #{state} #{issue_link} in #{project_link}: <b>#{title}</b>"]
message << "<pre>#{markdown(description)}</pre>"
message
message.join
end
def create_merge_request_message(data)
......@@ -181,16 +183,23 @@ class HipchatService < Service
state = obj_attr[:state]
description = obj_attr[:description]
title = render_line(obj_attr[:title])
<<<<<<< HEAD
action = obj_attr[:action]
state_or_action_text = action == 'approved' ? action : state
merge_request_url = "#{project_url}/merge_requests/#{merge_request_iid}"
merge_request_link = "<a href=\"#{merge_request_url}\">merge request !#{merge_request_iid}</a>"
message = "#{user_name} #{state_or_action_text} #{merge_request_link} in " \
"#{project_link}: <b>#{title}</b>"
=======
message << "<pre>#{markdown(description)}</pre>"
merge_request_url = "#{project_url}/merge_requests/#{merge_request_id}"
merge_request_link = "<a href=\"#{merge_request_url}\">merge request !#{merge_request_id}</a>"
message = ["#{user_name} #{state} #{merge_request_link} in " \
"#{project_link}: <b>#{title}</b>"]
>>>>>>> upstream/master
message
message << "<pre>#{markdown(description)}</pre>"
message.join
end
def format_title(title)
......@@ -236,12 +245,11 @@ class HipchatService < Service
end
subject_html = "<a href=\"#{note_url}\">#{subject_type} #{subject_desc}</a>"
message = "#{user_name} commented on #{subject_html} in #{project_link}: "
message = ["#{user_name} commented on #{subject_html} in #{project_link}: "]
message << title
message << "<pre>#{markdown(note, ref: commit_id)}</pre>"
message
message.join
end
def create_pipeline_message(data)
......
# frozen_string_literal: true
require 'uri'
class IrkerService < Service
......
# frozen_string_literal: true
class IssueTrackerService < Service
validate :one_issue_tracker, if: :activated?, on: :manual_change
......
# frozen_string_literal: true
class JiraService < IssueTrackerService
include Gitlab::Routing
include ApplicationHelper
......
# frozen_string_literal: true
##
# NOTE:
# We'll move this class to Clusters::Platforms::Kubernetes, which contains exactly the same logic.
......
# frozen_string_literal: true
class MattermostService < ChatNotificationService
def title
'Mattermost notifications'
......
# frozen_string_literal: true
class MattermostSlashCommandsService < SlashCommandsService
include TriggersHelper
......
# frozen_string_literal: true
class MicrosoftTeamsService < ChatNotificationService
def title
'Microsoft Teams Notification'
......
# frozen_string_literal: true
# For an example companion mocking service, see https://gitlab.com/gitlab-org/gitlab-mock-ci-service
class MockCiService < CiService
ALLOWED_STATES = %w[failed canceled running pending success success_with_warnings skipped not_found].freeze
......
# frozen_string_literal: true
class MockDeploymentService < DeploymentService
def title
'Mock deployment'
......
# frozen_string_literal: true
class MockMonitoringService < MonitoringService
def title
'Mock monitoring'
......
# frozen_string_literal: true
# Base class for monitoring services
#
# These services integrate with a deployment solution like Prometheus
......
# frozen_string_literal: true
class PackagistService < Service
prop_accessor :username, :token, :server
......
# frozen_string_literal: true
class PipelinesEmailService < Service
prop_accessor :recipients
boolean_accessor :notify_only_broken_pipelines
......
# frozen_string_literal: true
class PivotaltrackerService < Service
API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits'.freeze
......
# frozen_string_literal: true
class PrometheusService < MonitoringService
include PrometheusAdapter
......
# frozen_string_literal: true
class PushoverService < Service
BASE_URI = 'https://api.pushover.net/1'.freeze
......@@ -79,7 +81,7 @@ class PushoverService < Service
end
if data[:total_commits_count] > 0
message << "\nTotal commits count: #{data[:total_commits_count]}"
message = [message, "Total commits count: #{data[:total_commits_count]}"].join("\n")
end
pushover_data = {
......
# frozen_string_literal: true
class RedmineService < IssueTrackerService
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
......
# frozen_string_literal: true
class SlackService < ChatNotificationService
def title
'Slack notifications'
......
# frozen_string_literal: true
class SlackSlashCommandsService < SlashCommandsService
prepend EE::SlackSlashCommandsService
include TriggersHelper
......
# frozen_string_literal: true
# Base class for Chat services
# This class is not meant to be used directly, but only to inherrit from.
class SlashCommandsService < Service
......
# frozen_string_literal: true
class TeamcityService < CiService
include ReactiveService
......
# frozen_string_literal: true
class ProtectedBranch::MergeAccessLevel < ActiveRecord::Base
include ProtectedBranchAccess
end
# frozen_string_literal: true
class ProtectedBranch::PushAccessLevel < ActiveRecord::Base
include ProtectedBranchAccess
end
# frozen_string_literal: true
class ProtectedTag::CreateAccessLevel < ActiveRecord::Base
include ProtectedTagAccess
......
# frozen_string_literal: true
class RepositoryLanguage < ActiveRecord::Base
belongs_to :project
belongs_to :programming_language
......
# frozen_string_literal: true
class SiteStatistic < ActiveRecord::Base
# prevents the creation of multiple rows
default_value_for :id, 1
......
# frozen_string_literal: true
module Storage
class HashedProject
attr_accessor :project
......
# frozen_string_literal: true
module Storage
class LegacyProject
attr_accessor :project
......
......@@ -47,10 +47,13 @@ class EnvironmentEntity < Grape::Entity
request.current_user
end
<<<<<<< HEAD
def can_read_deploy_board?
can?(current_user, :read_deploy_board, environment.project)
end
=======
>>>>>>> upstream/master
def can_access_terminal?
can?(request.current_user, :create_environment_terminal, environment)
end
......
# frozen_string_literal: true
module Ci
class EnqueueBuildService < BaseService
<<<<<<< HEAD
prepend EE::Ci::EnqueueBuildService
=======
>>>>>>> upstream/master
def execute(build)
build.enqueue
end
......
......@@ -4,7 +4,11 @@
= _('The repository must be accessible over <code>http://</code>,
<code>https://</code>, <code>ssh://</code> and <code>git://</code>.').html_safe
%li= _('Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>.').html_safe
<<<<<<< HEAD
%li= _("The update action will time out after #{import_will_timeout_message(Gitlab.config.gitlab_shell.git_timeout)} minutes. For big repositories, use a clone/push combination.")
=======
%li= _('The update action will time out after 15 minutes. For big repositories, use a clone/push combination.')
>>>>>>> upstream/master
%li= _('The Git LFS objects will <strong>not</strong> be synced.').html_safe
%li
= _('This user will be the author of all events in the activity feed that are the result of an update,
......
......@@ -12,15 +12,26 @@
.settings-content
= form_for @project, url: project_mirror_path(@project), html: { class: 'gl-show-field-errors js-mirror-form', autocomplete: 'false', data: mirrors_form_data_attributes } do |f|
<<<<<<< HEAD
.card
.card-header
%h3.card-title= _('Mirror a repository')
.card-body
=======
.panel.panel-default
.panel-heading
%h3.panel-title= _('Mirror a repository')
.panel-body
>>>>>>> upstream/master
%div= form_errors(@project)
.form-group.has-feedback
= label_tag :url, _('Git repository URL'), class: 'label-light'
<<<<<<< HEAD
= text_field_tag :url, nil, class: 'form-control js-mirror-url js-repo-url', placeholder: _('Input your repository URL'), required: true, pattern: "(#{protocols}):\/\/.+", title: 'A valid repository URL is required'
=======
= text_field_tag :url, nil, class: 'form-control js-mirror-url js-repo-url', placeholder: _('Input your repository URL'), required: true, pattern: "(#{protocols}):\/\/.+"
>>>>>>> upstream/master
= render 'projects/mirrors/instructions'
......@@ -29,12 +40,21 @@
.form-check.append-bottom-10
= check_box_tag :only_protected_branches, '1', false, class: 'js-mirror-protected form-check-input'
= label_tag :only_protected_branches, _('Only mirror protected branches'), class: 'form-check-label'
<<<<<<< HEAD
= link_to icon('question-circle'), help_page_path('user/project/protected_branches'), target: '_blank'
.card-footer
= f.submit _('Mirror repository'), class: 'btn btn-create', name: :update_remote_mirror
.card
=======
= link_to icon('question-circle'), help_page_path('user/project/protected_branches')
.panel-footer
= f.submit _('Mirror repository'), class: 'btn btn-create', name: :update_remote_mirror
.panel.panel-default
>>>>>>> upstream/master
.table-responsive
%table.table.push-pull-table
%thead
......
......@@ -11,7 +11,11 @@
.form-group
= label_tag :auth_method, _('Authentication method'), class: 'label-bold'
<<<<<<< HEAD
= select_tag :auth_method, options_for_select([[[_('None'), 'none'], [_('Password'), 'password']], 'none'), { class: "form-control js-auth-method" }
=======
= select_tag :auth_method, options_for_select([[_('None'), 'none'], [_('Password'), 'password']], 'none'), { class: "form-control js-auth-method" }
>>>>>>> upstream/master
.form-group.js-password-group.collapse
= label_tag :password, _('Password'), class: 'label-bold'
......
---
title: CE Port of Protected Environments backend
merge_request: 20859
author:
type: other
---
title: Add the ability to reference projects in comments and other markdown text.
merge_request: 20285
author: Reuben Pereira
type: added
---
title: Allows to cancel a Created job
merge_request: 20635
author: Jacopo Beschi @jacopo-beschi
type: added
---
title: Enable frozen string in rest of app/models/**/*.rb
merge_request: gfyoung
author:
type: performance
---
title: Rails5 fix specs duplicate key value violates unique constraint 'index_gpg_signatures_on_commit_sha'
merge_request: 21119
author: Jasper Maes
type: fixed
......@@ -260,6 +260,7 @@ GFM will recognize the following:
| `@user_name` | specific user |
| `@group_name` | specific group |
| `@all` | entire team |
| `namespace/project>` | project |
| `#12345` | issue |
| `!123` | merge request |
| `$123` | snippet |
......
......@@ -1147,7 +1147,6 @@ X-Gitlab-Event: Build Hook
},
"repository": {
"name": "gitlab_test",
"git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
"description": "Atque in sunt eos similique dolores voluptatem.",
"homepage": "http://192.168.64.1:3005/gitlab-org/gitlab-test",
"git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
......
module Banzai
module Filter
# HTML filter that replaces project references with links.
class ProjectReferenceFilter < ReferenceFilter
self.reference_type = :project
# Public: Find `namespace/project>` project references in text
#
# ProjectReferenceFilter.references_in(text) do |match, project|
# "<a href=...>#{project}></a>"
# end
#
# text - String text to search.
#
# Yields the String match, and the String project name.
#
# Returns a String replaced with the return of the block.
def self.references_in(text)
text.gsub(Project.markdown_reference_pattern) do |match|
yield match, "#{$~[:namespace]}/#{$~[:project]}"
end
end
def call
ref_pattern = Project.markdown_reference_pattern
ref_pattern_start = /\A#{ref_pattern}\z/
nodes.each do |node|
if text_node?(node)
replace_text_when_pattern_matches(node, ref_pattern) do |content|
project_link_filter(content)
end
elsif element_node?(node)
yield_valid_link(node) do |link, inner_html|
if link =~ ref_pattern_start
replace_link_node_with_href(node, link) do
project_link_filter(link, link_content: inner_html)
end
end
end
end
end
doc
end
# Replace `namespace/project>` project references in text with links to the referenced
# project page.
#
# text - String text to replace references in.
# link_content - Original content of the link being replaced.
#
# Returns a String with `namespace/project>` references replaced with links. All links
# have `gfm` and `gfm-project` class names attached for styling.
def project_link_filter(text, link_content: nil)
self.class.references_in(text) do |match, project_path|
cached_call(:banzai_url_for_object, match, path: [Project, project_path.downcase]) do
if project = projects_hash[project_path.downcase]
link_to_project(project, link_content: link_content) || match
else
match
end
end
end
end
# Returns a Hash containing all Project objects for the project
# references in the current document.
#
# The keys of this Hash are the project paths, the values the
# corresponding Project objects.
def projects_hash
@projects ||= Project.eager_load(:route, namespace: [:route])
.where_full_path_in(projects)
.index_by(&:full_path)
.transform_keys(&:downcase)
end
# Returns all projects referenced in the current document.
def projects
refs = Set.new
nodes.each do |node|
node.to_html.scan(Project.markdown_reference_pattern) do
refs << "#{$~[:namespace]}/#{$~[:project]}"
end
end
refs.to_a
end
private
def urls
Gitlab::Routing.url_helpers
end
def link_class
reference_class(:project)
end
def link_to_project(project, link_content: nil)
url = urls.project_url(project, only_path: context[:only_path])
data = data_attribute(project: project.id)
content = link_content || project.to_reference_with_postfix
link_tag(url, data, content, project.name)
end
def link_tag(url, data, link_content, title)
%(<a href="#{url}" #{data} class="#{link_class}" title="#{escape_once(title)}">#{link_content}</a>)
end
end
end
end
......@@ -38,6 +38,7 @@ module Banzai
def self.reference_filters
[
Filter::UserReferenceFilter,
Filter::ProjectReferenceFilter,
Filter::IssueReferenceFilter,
Filter::ExternalIssueReferenceFilter,
Filter::MergeRequestReferenceFilter,
......
module Banzai
module ReferenceParser
class ProjectParser < BaseParser
include Gitlab::Utils::StrongMemoize
self.reference_type = :project
def references_relation
Project
end
private
# Returns an Array of Project ids that can be read by the given user.
#
# user - The User for which to check the projects
def readable_project_ids_for(user)
@project_ids_by_user ||= {}
@project_ids_by_user[user] ||=
Project.public_or_visible_to_user(user).where("projects.id IN (?)", @projects_for_nodes.values.map(&:id)).pluck(:id)
end
def can_read_reference?(user, ref_project, node)
readable_project_ids_for(user).include?(ref_project.try(:id))
end
end
end
end
......@@ -2867,6 +2867,7 @@ msgstr ""
msgid "Environments|You don't have any environments right now."
msgstr ""
<<<<<<< HEAD
msgid "Environments|protected"
msgstr ""
......@@ -2906,6 +2907,8 @@ msgstr ""
msgid "Epics|start"
msgstr ""
=======
>>>>>>> upstream/master
msgid "Error"
msgstr ""
......@@ -3966,9 +3969,12 @@ msgstr ""
msgid "Inline"
msgstr ""
<<<<<<< HEAD
msgid "Input host keys manually"
msgstr ""
=======
>>>>>>> upstream/master
msgid "Input your repository URL"
msgstr ""
......@@ -4626,6 +4632,21 @@ msgstr ""
msgid "Mirroring repositories"
msgstr ""
msgid "Mirror a repository"
msgstr ""
msgid "Mirror direction"
msgstr ""
msgid "Mirror repository"
msgstr ""
msgid "Mirrored repositories"
msgstr ""
msgid "Mirroring repositories"
msgstr ""
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
......@@ -5788,6 +5809,7 @@ msgstr ""
msgid "Public pipelines"
msgstr ""
<<<<<<< HEAD
msgid "Pull"
msgstr ""
......@@ -5797,6 +5819,11 @@ msgstr ""
msgid "Push Rules"
msgstr ""
=======
msgid "Push"
msgstr ""
>>>>>>> upstream/master
msgid "Push events"
msgstr ""
......@@ -6304,9 +6331,12 @@ msgstr ""
msgid "Set up Koding"
msgstr ""
<<<<<<< HEAD
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
=======
>>>>>>> upstream/master
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
......@@ -6791,12 +6821,15 @@ msgstr ""
msgid "Test coverage parsing"
msgstr ""
<<<<<<< HEAD
msgid "Thanks! Don't show me this again"
msgstr ""
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
=======
>>>>>>> upstream/master
msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
......@@ -6908,6 +6941,9 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after 15 minutes. For big repositories, use a clone/push combination."
msgstr ""
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
......@@ -7076,6 +7112,7 @@ msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
<<<<<<< HEAD
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
msgstr ""
......@@ -7085,6 +7122,8 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
=======
>>>>>>> upstream/master
msgid "Time before an issue gets scheduled"
msgstr ""
......@@ -7458,6 +7497,7 @@ msgstr ""
msgid "Updating"
msgstr ""
<<<<<<< HEAD
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr ""
......@@ -7473,6 +7513,8 @@ msgstr ""
msgid "Upgrade your plan to improve Issue boards."
msgstr ""
=======
>>>>>>> upstream/master
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr ""
......
require 'spec_helper'
describe 'Blob shortcuts' do
describe 'Blob shortcuts', :js do
include TreeHelper
let(:project) { create(:project, :public, :repository) }
let(:path) { project.repository.ls_files(project.repository.root_ref)[0] }
......
......@@ -210,7 +210,7 @@ describe "User browses files" do
end
end
context "when browsing a file content" do
context "when browsing a file content", :js do
before do
visit(tree_path_root_ref)
......
require 'spec_helper'
describe 'Projects > Files > User deletes files' do
describe 'Projects > Files > User deletes files', :js do
let(:fork_message) do
"You're not allowed to make changes to this project directly. "\
"A fork of this project has been created that you can make changes in, so you can submit a merge request."
......
require 'spec_helper'
describe 'Projects > Files > User edits files' do
describe 'Projects > Files > User edits files', :js do
include ProjectForksHelper
let(:project) { create(:project, :repository, name: 'Shop') }
let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
......
require 'spec_helper'
describe 'Projects > Files > User replaces files' do
describe 'Projects > Files > User replaces files', :js do
include DropzoneHelper
let(:fork_message) do
......
require 'spec_helper'
describe Banzai::Filter::ProjectReferenceFilter do
include FilterSpecHelper
def invalidate_reference(reference)
"#{reference.reverse}"
end
def get_reference(project)
project.to_reference_with_postfix
end
let(:project) { create(:project, :public) }
subject { project }
let(:subject_name) { "project" }
let(:reference) { get_reference(project) }
it_behaves_like 'user reference or project reference'
it 'ignores invalid projects' do
exp = act = "Hey #{invalidate_reference(reference)}"
expect(reference_filter(act).to_html).to eq(CGI.escapeHTML(exp))
end
it 'allows references with text after the > character' do
doc = reference_filter("Hey #{reference}foo")
expect(doc.css('a').first.attr('href')).to eq urls.project_url(subject)
end
%w(pre code a style).each do |elem|
it "ignores valid references contained inside '#{elem}' element" do
exp = act = "<#{elem}>Hey #{CGI.escapeHTML(reference)}</#{elem}>"
expect(reference_filter(act).to_html).to eq exp
end
end
it 'includes default classes' do
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-project has-tooltip'
end
context 'in group context' do
let(:group) { create(:group) }
let(:project) { create(:project, group: group) }
let(:nested_group) { create(:group, :nested) }
let(:nested_project) { create(:project, group: nested_group) }
it 'supports mentioning a project' do
reference = get_reference(project)
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.project_url(project)
end
it 'supports mentioning a project in a nested group' do
reference = get_reference(nested_project)
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.project_url(nested_project)
end
end
describe '#projects_hash' do
it 'returns a Hash containing all Projects' do
document = Nokogiri::HTML.fragment("<p>#{get_reference(project)}</p>")
filter = described_class.new(document, project: project)
expect(filter.projects_hash).to eq({ project.full_path => project })
end
end
describe '#projects' do
it 'returns the projects mentioned in a document' do
document = Nokogiri::HTML.fragment("<p>#{get_reference(project)}</p>")
filter = described_class.new(document, project: project)
expect(filter.projects).to eq([project.full_path])
end
end
end
......@@ -3,9 +3,17 @@ require 'spec_helper'
describe Banzai::Filter::UserReferenceFilter do
include FilterSpecHelper
def get_reference(user)
user.to_reference
end
let(:project) { create(:project, :public) }
let(:user) { create(:user) }
let(:reference) { user.to_reference }
subject { user }
let(:subject_name) { "user" }
let(:reference) { get_reference(user) }
it_behaves_like 'user reference or project reference'
it 'requires project context' do
expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
......@@ -66,45 +74,6 @@ describe Banzai::Filter::UserReferenceFilter do
end
end
context 'mentioning a user' do
it_behaves_like 'a reference containing an element node'
it 'links to a User' do
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.user_url(user)
end
it 'links to a User with a period' do
user = create(:user, name: 'alphA.Beta')
doc = reference_filter("Hey #{user.to_reference}")
expect(doc.css('a').length).to eq 1
end
it 'links to a User with an underscore' do
user = create(:user, name: 'ping_pong_king')
doc = reference_filter("Hey #{user.to_reference}")
expect(doc.css('a').length).to eq 1
end
it 'links to a User with different case-sensitivity' do
user = create(:user, username: 'RescueRanger')
doc = reference_filter("Hey #{user.to_reference.upcase}")
expect(doc.css('a').length).to eq 1
expect(doc.css('a').text).to eq(user.to_reference)
end
it 'includes a data-user attribute' do
doc = reference_filter("Hey #{reference}")
link = doc.css('a').first
expect(link).to have_attribute('data-user')
expect(link.attr('data-user')).to eq user.namespace.owner_id.to_s
end
end
context 'mentioning a group' do
it_behaves_like 'a reference containing an element node'
......@@ -154,36 +123,6 @@ describe Banzai::Filter::UserReferenceFilter do
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-project_member has-tooltip'
end
it 'supports an :only_path context' do
doc = reference_filter("Hey #{reference}", only_path: true)
link = doc.css('a').first.attr('href')
expect(link).not_to match %r(https?://)
expect(link).to eq urls.user_path(user)
end
context 'referencing a user in a link href' do
let(:reference) { %Q{<a href="#{user.to_reference}">User</a>} }
it 'links to a User' do
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.user_url(user)
end
it 'links with adjacent text' do
doc = reference_filter("Mention me (#{reference}.)")
expect(doc.to_html).to match(%r{\(<a.+>User</a>\.\)})
end
it 'includes a data-user attribute' do
doc = reference_filter("Hey #{reference}")
link = doc.css('a').first
expect(link).to have_attribute('data-user')
expect(link.attr('data-user')).to eq user.namespace.owner_id.to_s
end
end
context 'when a project is not specified' do
let(:project) { nil }
......@@ -227,7 +166,7 @@ describe Banzai::Filter::UserReferenceFilter do
end
it 'supports mentioning a single user' do
reference = group_member.to_reference
reference = get_reference(group_member)
doc = reference_filter("Hey #{reference}", context)
expect(doc.css('a').first.attr('href')).to eq urls.user_url(group_member)
......@@ -243,7 +182,7 @@ describe Banzai::Filter::UserReferenceFilter do
describe '#namespaces' do
it 'returns a Hash containing all Namespaces' do
document = Nokogiri::HTML.fragment("<p>#{user.to_reference}</p>")
document = Nokogiri::HTML.fragment("<p>#{get_reference(user)}</p>")
filter = described_class.new(document, project: project)
ns = user.namespace
......@@ -253,7 +192,7 @@ describe Banzai::Filter::UserReferenceFilter do
describe '#usernames' do
it 'returns the usernames mentioned in a document' do
document = Nokogiri::HTML.fragment("<p>#{user.to_reference}</p>")
document = Nokogiri::HTML.fragment("<p>#{get_reference(user)}</p>")
filter = described_class.new(document, project: project)
expect(filter.usernames).to eq([user.username])
......
require 'spec_helper'
describe Banzai::ReferenceParser::ProjectParser do
include ReferenceParserHelpers
let(:project) { create(:project, :public) }
let(:user) { create(:user) }
subject { described_class.new(Banzai::RenderContext.new(project, user)) }
let(:link) { empty_html_link }
describe '#referenced_by' do
describe 'when the link has a data-project attribute' do
context 'using an existing project ID' do
it 'returns an Array of projects' do
link['data-project'] = project.id.to_s
expect(subject.gather_references([link])).to eq([project])
end
end
context 'using a non-existing project ID' do
it 'returns an empty Array' do
link['data-project'] = ''
expect(subject.gather_references([link])).to eq([])
end
end
context 'using a private project ID' do
it 'returns an empty Array when unauthorized' do
private_project = create(:project, :private)
link['data-project'] = private_project.id.to_s
expect(subject.gather_references([link])).to eq([])
end
it 'returns an Array when authorized' do
private_project = create(:project, :private, namespace: user.namespace)
link['data-project'] = private_project.id.to_s
expect(subject.gather_references([link])).to eq([private_project])
end
end
end
end
end
......@@ -1104,6 +1104,12 @@ describe Ci::Build do
it { is_expected.to be_cancelable }
end
context 'when build is created' do
let(:build) { create(:ci_build, :created) }
it { is_expected.to be_cancelable }
end
end
context 'when build is not cancelable' do
......
......@@ -399,6 +399,15 @@ describe Project do
it { is_expected.to delegate_method(:name).to(:owner).with_prefix(true).with_arguments(allow_nil: true) }
end
describe '#to_reference_with_postfix' do
it 'returns the full path with reference_postfix' do
namespace = create(:namespace, path: 'sample-namespace')
project = create(:project, path: 'sample-project', namespace: namespace)
expect(project.to_reference_with_postfix).to eq 'sample-namespace/sample-project>'
end
end
describe '#to_reference' do
let(:owner) { create(:user, name: 'Gitlab') }
let(:namespace) { create(:namespace, path: 'sample-namespace', owner: owner) }
......
......@@ -11,3 +11,76 @@ shared_examples 'a reference containing an element node' do
expect(doc.children.first.inner_html).to eq(inner_html)
end
end
# Requires a reference, subject and subject_name:
# subject { create(:user) }
# let(:reference) { subject.to_reference }
# let(:subject_name) { 'user' }
shared_examples 'user reference or project reference' do
shared_examples 'it contains a data- attribute' do
it 'includes a data- attribute' do
doc = reference_filter("Hey #{reference}")
link = doc.css('a').first
expect(link).to have_attribute("data-#{subject_name}")
expect(link.attr("data-#{subject_name}")).to eq subject.id.to_s
end
end
context 'mentioning a resource' do
it_behaves_like 'a reference containing an element node'
it_behaves_like 'it contains a data- attribute'
it "links to a resource" do
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.send("#{subject_name}_url", subject)
end
it 'links to a resource with a period' do
subject = create(subject_name.to_sym, name: 'alphA.Beta')
doc = reference_filter("Hey #{get_reference(subject)}")
expect(doc.css('a').length).to eq 1
end
it 'links to a resource with an underscore' do
subject = create(subject_name.to_sym, name: 'ping_pong_king')
doc = reference_filter("Hey #{get_reference(subject)}")
expect(doc.css('a').length).to eq 1
end
it 'links to a resource with different case-sensitivity' do
subject = create(subject_name.to_sym, name: 'RescueRanger')
reference = get_reference(subject)
doc = reference_filter("Hey #{reference.upcase}")
expect(doc.css('a').length).to eq 1
expect(doc.css('a').text).to eq(reference)
end
end
it 'supports an :only_path context' do
doc = reference_filter("Hey #{reference}", only_path: true)
link = doc.css('a').first.attr('href')
expect(link).not_to match %r(https?://)
expect(link).to eq urls.send "#{subject_name}_path", subject
end
context 'referencing a resource in a link href' do
let(:reference) { %Q{<a href="#{get_reference(subject)}">Some text</a>} }
it_behaves_like 'it contains a data- attribute'
it 'links to the resource' do
doc = reference_filter("Hey #{reference}")
expect(doc.css('a').first.attr('href')).to eq urls.send "#{subject_name}_url", subject
end
it 'links with adjacent text' do
doc = reference_filter("Mention me (#{reference}.)")
expect(doc.to_html).to match(%r{\(<a.+>Some text</a>\.\)})
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