Merge branch 'master' into refactor-realtime-issue
This commit is contained in:
commit
1ed0673c25
|
@ -494,7 +494,13 @@ Style/TrailingBlankLines:
|
|||
|
||||
# This cop checks for trailing comma in array and hash literals.
|
||||
Style/TrailingCommaInLiteral:
|
||||
Enabled: false
|
||||
Enabled: true
|
||||
EnforcedStyleForMultiline: no_comma
|
||||
|
||||
# This cop checks for trailing comma in argument lists.
|
||||
Style/TrailingCommaInArguments:
|
||||
Enabled: true
|
||||
EnforcedStyleForMultiline: no_comma
|
||||
|
||||
# Checks for %W when interpolation is not needed.
|
||||
Style/UnneededCapitalW:
|
||||
|
|
|
@ -369,13 +369,6 @@ Style/SymbolProc:
|
|||
Style/TernaryParentheses:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 53
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyleForMultiline, SupportedStylesForMultiline.
|
||||
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
|
||||
Style/TrailingCommaInArguments:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 18
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowNamedUnderscoreVariables.
|
||||
|
|
|
@ -8,7 +8,10 @@ export default class BlobViewer {
|
|||
this.richViewer = document.querySelector('.blob-viewer[data-type="rich"]');
|
||||
this.$fileHolder = $('.file-holder');
|
||||
|
||||
let initialViewerName = document.querySelector('.blob-viewer:not(.hidden)').getAttribute('data-type');
|
||||
const initialViewer = document.querySelector('.blob-viewer:not(.hidden)');
|
||||
if (!initialViewer) return;
|
||||
|
||||
let initialViewerName = initialViewer.getAttribute('data-type');
|
||||
|
||||
this.initBindings();
|
||||
|
||||
|
|
|
@ -36,6 +36,9 @@ gl.issueBoards.BoardSidebar = Vue.extend({
|
|||
},
|
||||
assigneeId() {
|
||||
return this.issue.assignee ? this.issue.assignee.id : 0;
|
||||
},
|
||||
milestoneTitle() {
|
||||
return this.issue.milestone ? this.issue.milestone.title : 'No Milestone';
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -246,6 +246,7 @@ const ShortcutsBlob = require('./shortcuts_blob');
|
|||
new NotificationsForm();
|
||||
if ($('#tree-slider').length) {
|
||||
new TreeView();
|
||||
new BlobViewer();
|
||||
}
|
||||
break;
|
||||
case 'projects:pipelines:builds':
|
||||
|
@ -300,6 +301,7 @@ const ShortcutsBlob = require('./shortcuts_blob');
|
|||
case 'projects:tree:show':
|
||||
shortcut_handler = new ShortcutsNavigation();
|
||||
new TreeView();
|
||||
new BlobViewer();
|
||||
gl.TargetBranchDropDown.bootstrap();
|
||||
break;
|
||||
case 'projects:find_file:show':
|
||||
|
|
|
@ -1,32 +1,54 @@
|
|||
const AjaxCache = {
|
||||
internalStorage: { },
|
||||
class AjaxCache {
|
||||
constructor() {
|
||||
this.internalStorage = { };
|
||||
this.pendingRequests = { };
|
||||
}
|
||||
|
||||
get(endpoint) {
|
||||
return this.internalStorage[endpoint];
|
||||
},
|
||||
}
|
||||
|
||||
hasData(endpoint) {
|
||||
return Object.prototype.hasOwnProperty.call(this.internalStorage, endpoint);
|
||||
},
|
||||
purge(endpoint) {
|
||||
}
|
||||
|
||||
remove(endpoint) {
|
||||
delete this.internalStorage[endpoint];
|
||||
},
|
||||
}
|
||||
|
||||
retrieve(endpoint) {
|
||||
if (AjaxCache.hasData(endpoint)) {
|
||||
return Promise.resolve(AjaxCache.get(endpoint));
|
||||
if (this.hasData(endpoint)) {
|
||||
return Promise.resolve(this.get(endpoint));
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
$.ajax(endpoint) // eslint-disable-line promise/catch-or-return
|
||||
.then(data => resolve(data),
|
||||
(jqXHR, textStatus, errorThrown) => {
|
||||
const error = new Error(`${endpoint}: ${errorThrown}`);
|
||||
error.textStatus = textStatus;
|
||||
reject(error);
|
||||
},
|
||||
);
|
||||
})
|
||||
.then((data) => { this.internalStorage[endpoint] = data; })
|
||||
.then(() => AjaxCache.get(endpoint));
|
||||
},
|
||||
};
|
||||
let pendingRequest = this.pendingRequests[endpoint];
|
||||
|
||||
export default AjaxCache;
|
||||
if (!pendingRequest) {
|
||||
pendingRequest = new Promise((resolve, reject) => {
|
||||
// jQuery 2 is not Promises/A+ compatible (missing catch)
|
||||
$.ajax(endpoint) // eslint-disable-line promise/catch-or-return
|
||||
.then(data => resolve(data),
|
||||
(jqXHR, textStatus, errorThrown) => {
|
||||
const error = new Error(`${endpoint}: ${errorThrown}`);
|
||||
error.textStatus = textStatus;
|
||||
reject(error);
|
||||
},
|
||||
);
|
||||
})
|
||||
.then((data) => {
|
||||
this.internalStorage[endpoint] = data;
|
||||
delete this.pendingRequests[endpoint];
|
||||
})
|
||||
.catch((error) => {
|
||||
delete this.pendingRequests[endpoint];
|
||||
throw error;
|
||||
});
|
||||
|
||||
this.pendingRequests[endpoint] = pendingRequest;
|
||||
}
|
||||
|
||||
return pendingRequest.then(() => this.get(endpoint));
|
||||
}
|
||||
}
|
||||
|
||||
export default new AjaxCache();
|
||||
|
|
|
@ -18,12 +18,11 @@
|
|||
}
|
||||
|
||||
$els.each(function(i, dropdown) {
|
||||
var $block, $dropdown, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, collapsedSidebarLabelTemplate, defaultLabel, issuableId, issueUpdateURL, milestoneLinkNoneTemplate, milestoneLinkTemplate, milestonesUrl, projectId, selectedMilestone, showAny, showNo, showUpcoming, showStarted, useId, showMenuAbove;
|
||||
var $block, $dropdown, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, collapsedSidebarLabelTemplate, defaultLabel, defaultNo, issuableId, issueUpdateURL, milestoneLinkNoneTemplate, milestoneLinkTemplate, milestonesUrl, projectId, selectedMilestone, selectedMilestoneDefault, showAny, showNo, showUpcoming, showStarted, useId, showMenuAbove;
|
||||
$dropdown = $(dropdown);
|
||||
projectId = $dropdown.data('project-id');
|
||||
milestonesUrl = $dropdown.data('milestones');
|
||||
issueUpdateURL = $dropdown.data('issueUpdate');
|
||||
selectedMilestone = $dropdown.data('selected');
|
||||
showNo = $dropdown.data('show-no');
|
||||
showAny = $dropdown.data('show-any');
|
||||
showMenuAbove = $dropdown.data('showMenuAbove');
|
||||
|
@ -31,6 +30,7 @@
|
|||
showStarted = $dropdown.data('show-started');
|
||||
useId = $dropdown.data('use-id');
|
||||
defaultLabel = $dropdown.data('default-label');
|
||||
defaultNo = $dropdown.data('default-no');
|
||||
issuableId = $dropdown.data('issuable-id');
|
||||
abilityName = $dropdown.data('ability-name');
|
||||
$selectbox = $dropdown.closest('.selectbox');
|
||||
|
@ -38,6 +38,9 @@
|
|||
$sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon');
|
||||
$value = $block.find('.value');
|
||||
$loading = $block.find('.block-loading').fadeOut();
|
||||
selectedMilestoneDefault = (showAny ? '' : null);
|
||||
selectedMilestoneDefault = (showNo && defaultNo ? 'No Milestone' : selectedMilestoneDefault);
|
||||
selectedMilestone = $dropdown.data('selected') || selectedMilestoneDefault;
|
||||
if (issueUpdateURL) {
|
||||
milestoneLinkTemplate = _.template('<a href="/<%- full_path %>/milestones/<%- iid %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %></a>');
|
||||
milestoneLinkNoneTemplate = '<span class="no-value">None</span>';
|
||||
|
@ -86,8 +89,18 @@
|
|||
if (showMenuAbove) {
|
||||
$dropdown.data('glDropdown').positionMenuAbove();
|
||||
}
|
||||
$(`[data-milestone-id="${selectedMilestone}"] > a`).addClass('is-active');
|
||||
});
|
||||
},
|
||||
renderRow: function(milestone) {
|
||||
return `
|
||||
<li data-milestone-id="${milestone.name}">
|
||||
<a href='#' class='dropdown-menu-milestone-link'>
|
||||
${_.escape(milestone.title)}
|
||||
</a>
|
||||
</li>
|
||||
`;
|
||||
},
|
||||
filterable: true,
|
||||
search: {
|
||||
fields: ['title']
|
||||
|
@ -120,15 +133,24 @@
|
|||
// display:block overrides the hide-collapse rule
|
||||
return $value.css('display', '');
|
||||
},
|
||||
opened: function(e) {
|
||||
const $el = $(e.currentTarget);
|
||||
if ($dropdown.hasClass('js-issue-board-sidebar')) {
|
||||
selectedMilestone = $dropdown[0].dataset.selected || selectedMilestoneDefault;
|
||||
}
|
||||
$('a.is-active', $el).removeClass('is-active');
|
||||
$(`[data-milestone-id="${selectedMilestone}"] > a`, $el).addClass('is-active');
|
||||
},
|
||||
vue: $dropdown.hasClass('js-issue-board-sidebar'),
|
||||
clicked: function(options) {
|
||||
const { $el, e } = options;
|
||||
let selected = options.selectedObj;
|
||||
|
||||
var data, isIssueIndex, isMRIndex, page, boardsStore;
|
||||
var data, isIssueIndex, isMRIndex, isSelecting, page, boardsStore;
|
||||
page = $('body').data('page');
|
||||
isIssueIndex = page === 'projects:issues:index';
|
||||
isMRIndex = (page === page && page === 'projects:merge_requests:index');
|
||||
isSelecting = (selected.name !== selectedMilestone);
|
||||
selectedMilestone = isSelecting ? selected.name : selectedMilestoneDefault;
|
||||
if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
@ -142,16 +164,11 @@
|
|||
boardsStore[$dropdown.data('field-name')] = selected.name;
|
||||
e.preventDefault();
|
||||
} else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
|
||||
if (selected.name != null) {
|
||||
selectedMilestone = selected.name;
|
||||
} else {
|
||||
selectedMilestone = '';
|
||||
}
|
||||
return Issuable.filterResults($dropdown.closest('form'));
|
||||
} else if ($dropdown.hasClass('js-filter-submit')) {
|
||||
return $dropdown.closest('form').submit();
|
||||
} else if ($dropdown.hasClass('js-issue-board-sidebar')) {
|
||||
if (selected.id !== -1) {
|
||||
if (selected.id !== -1 && isSelecting) {
|
||||
gl.issueBoards.boardStoreIssueSet('milestone', new ListMilestone({
|
||||
id: selected.id,
|
||||
title: selected.name
|
||||
|
|
|
@ -312,7 +312,7 @@
|
|||
}
|
||||
|
||||
.empty-state {
|
||||
margin: 100px 0 0;
|
||||
margin: 5% auto 0;
|
||||
|
||||
.text-content {
|
||||
max-width: 460px;
|
||||
|
@ -335,27 +335,12 @@
|
|||
}
|
||||
|
||||
.btn {
|
||||
margin: $btn-side-margin $btn-side-margin 0 0;
|
||||
}
|
||||
margin: $btn-side-margin 5px;
|
||||
|
||||
@media(max-width: $screen-xs-max) {
|
||||
margin-top: 50px;
|
||||
text-align: center;
|
||||
|
||||
.btn {
|
||||
@media(max-width: $screen-xs-max) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: $screen-xs-max) {
|
||||
&.merge-requests .text-content {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
&.labels .text-content {
|
||||
margin-top: 70px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flex-container-block {
|
||||
|
|
|
@ -51,6 +51,7 @@ ul.related-merge-requests > li {
|
|||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.merge-request-id {
|
||||
flex-shrink: 0;
|
||||
|
@ -59,6 +60,14 @@ ul.related-merge-requests > li {
|
|||
.merge-request-info {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.row_title {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
gl-emoji {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.merge-requests-title,
|
||||
|
@ -114,7 +123,6 @@ ul.related-merge-requests > li {
|
|||
.related-merge-requests {
|
||||
.ci-status-link {
|
||||
display: block;
|
||||
margin-top: 3px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
margin: 5% auto 0;
|
||||
}
|
||||
|
||||
.table-holder {
|
||||
width: 100%;
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ class AutocompleteController < ApplicationController
|
|||
|
||||
no_project = {
|
||||
id: 0,
|
||||
name_with_namespace: 'No project',
|
||||
name_with_namespace: 'No project'
|
||||
}
|
||||
projects.unshift(no_project) unless params[:offset_id].present?
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ module LfsRequest
|
|||
render(
|
||||
json: {
|
||||
message: 'Git LFS is not enabled on this GitLab server, contact your admin.',
|
||||
documentation_url: help_url,
|
||||
documentation_url: help_url
|
||||
},
|
||||
status: 501
|
||||
)
|
||||
|
@ -48,7 +48,7 @@ module LfsRequest
|
|||
render(
|
||||
json: {
|
||||
message: 'Access forbidden. Check your access level.',
|
||||
documentation_url: help_url,
|
||||
documentation_url: help_url
|
||||
},
|
||||
content_type: "application/vnd.git-lfs+json",
|
||||
status: 403
|
||||
|
@ -59,7 +59,7 @@ module LfsRequest
|
|||
render(
|
||||
json: {
|
||||
message: 'Not found.',
|
||||
documentation_url: help_url,
|
||||
documentation_url: help_url
|
||||
},
|
||||
content_type: "application/vnd.git-lfs+json",
|
||||
status: 404
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
class Dashboard::SnippetsController < Dashboard::ApplicationController
|
||||
def index
|
||||
@snippets = SnippetsFinder.new.execute(
|
||||
@snippets = SnippetsFinder.new(
|
||||
current_user,
|
||||
filter: :by_user,
|
||||
user: current_user,
|
||||
author: current_user,
|
||||
scope: params[:scope]
|
||||
)
|
||||
).execute
|
||||
@snippets = @snippets.page(params[:page])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Explore::GroupsController < Explore::ApplicationController
|
||||
def index
|
||||
@groups = GroupsFinder.new.execute(current_user)
|
||||
@groups = GroupsFinder.new(current_user).execute
|
||||
@groups = @groups.search(params[:filter_groups]) if params[:filter_groups].present?
|
||||
@groups = @groups.sort(@sort = params[:sort])
|
||||
@groups = @groups.page(params[:page])
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Explore::SnippetsController < Explore::ApplicationController
|
||||
def index
|
||||
@snippets = SnippetsFinder.new.execute(current_user, filter: :all)
|
||||
@snippets = SnippetsFinder.new(current_user).execute
|
||||
@snippets = @snippets.page(params[:page])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -64,7 +64,7 @@ class GroupsController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
def subgroups
|
||||
@nested_groups = group.children
|
||||
@nested_groups = GroupsFinder.new(current_user, parent: group).execute
|
||||
@nested_groups = @nested_groups.search(params[:filter_groups]) if params[:filter_groups].present?
|
||||
end
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ class HealthController < ActionController::Base
|
|||
CHECKS = [
|
||||
Gitlab::HealthChecks::DbCheck,
|
||||
Gitlab::HealthChecks::RedisCheck,
|
||||
Gitlab::HealthChecks::FsShardsCheck,
|
||||
Gitlab::HealthChecks::FsShardsCheck
|
||||
].freeze
|
||||
|
||||
def readiness
|
||||
|
|
|
@ -4,7 +4,7 @@ class JwtController < ApplicationController
|
|||
before_action :authenticate_project_or_user
|
||||
|
||||
SERVICES = {
|
||||
Auth::ContainerRegistryAuthenticationService::AUDIENCE => Auth::ContainerRegistryAuthenticationService,
|
||||
Auth::ContainerRegistryAuthenticationService::AUDIENCE => Auth::ContainerRegistryAuthenticationService
|
||||
}.freeze
|
||||
|
||||
def auth
|
||||
|
|
|
@ -33,7 +33,7 @@ class Profiles::PreferencesController < Profiles::ApplicationController
|
|||
:color_scheme_id,
|
||||
:layout,
|
||||
:dashboard,
|
||||
:project_view,
|
||||
:project_view
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,7 +6,7 @@ class Projects::DeploymentsController < Projects::ApplicationController
|
|||
deployments = environment.deployments.reorder(created_at: :desc)
|
||||
deployments = deployments.where('created_at > ?', params[:after].to_time) if params[:after]&.to_time
|
||||
|
||||
render json: { deployments: DeploymentSerializer.new(user: @current_user, project: project)
|
||||
render json: { deployments: DeploymentSerializer.new(project: project)
|
||||
.represent_concise(deployments) }
|
||||
end
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
description: view_context.markdown_field(@issue, :description),
|
||||
description_text: @issue.description,
|
||||
task_status: @issue.task_status,
|
||||
updated_at: @issue.updated_at,
|
||||
updated_at: @issue.updated_at
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -268,7 +268,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
def issue_params
|
||||
params.require(:issue).permit(
|
||||
:title, :assignee_id, :position, :description, :confidential,
|
||||
:milestone_id, :due_date, :state_event, :task_num, :lock_version, label_ids: [], assignee_ids: [],
|
||||
:milestone_id, :due_date, :state_event, :task_num, :lock_version, label_ids: [], assignee_ids: []
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class Projects::LfsApiController < Projects::GitHttpClientController
|
|||
render(
|
||||
json: {
|
||||
message: 'Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.',
|
||||
documentation_url: "#{Gitlab.config.gitlab.url}/help",
|
||||
documentation_url: "#{Gitlab.config.gitlab.url}/help"
|
||||
},
|
||||
status: 501
|
||||
)
|
||||
|
@ -55,7 +55,7 @@ class Projects::LfsApiController < Projects::GitHttpClientController
|
|||
else
|
||||
object[:error] = {
|
||||
code: 404,
|
||||
message: "Object does not exist on the server or you don't have permissions to access it",
|
||||
message: "Object does not exist on the server or you don't have permissions to access it"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,7 +44,7 @@ class Projects::PipelinesController < Projects::ApplicationController
|
|||
all: @pipelines_count,
|
||||
running: @running_count,
|
||||
pending: @pending_count,
|
||||
finished: @finished_count,
|
||||
finished: @finished_count
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
@ -23,12 +23,11 @@ class Projects::SnippetsController < Projects::ApplicationController
|
|||
respond_to :html
|
||||
|
||||
def index
|
||||
@snippets = SnippetsFinder.new.execute(
|
||||
@snippets = SnippetsFinder.new(
|
||||
current_user,
|
||||
filter: :by_project,
|
||||
project: @project,
|
||||
scope: params[:scope]
|
||||
)
|
||||
).execute
|
||||
@snippets = @snippets.page(params[:page])
|
||||
if @snippets.out_of_range? && @snippets.total_pages != 0
|
||||
redirect_to namespace_project_snippets_path(page: @snippets.total_pages)
|
||||
|
|
|
@ -38,6 +38,8 @@ class Projects::TagsController < Projects::ApplicationController
|
|||
redirect_to namespace_project_tag_path(@project.namespace, @project, @tag.name)
|
||||
else
|
||||
@error = result[:message]
|
||||
@message = params[:message]
|
||||
@release_description = params[:release_description]
|
||||
render action: 'new'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -48,7 +48,7 @@ class Projects::TreeController < Projects::ApplicationController
|
|||
@dir_name = File.join(@path, params[:dir_name])
|
||||
@commit_params = {
|
||||
file_path: @dir_name,
|
||||
commit_message: params[:commit_message],
|
||||
commit_message: params[:commit_message]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -220,7 +220,7 @@ class ProjectsController < Projects::ApplicationController
|
|||
branches = BranchesFinder.new(@repository, params).execute.map(&:name)
|
||||
|
||||
options = {
|
||||
'Branches' => branches.take(100),
|
||||
'Branches' => branches.take(100)
|
||||
}
|
||||
|
||||
unless @repository.tag_count.zero?
|
||||
|
|
|
@ -27,12 +27,8 @@ class SnippetsController < ApplicationController
|
|||
|
||||
return render_404 unless @user
|
||||
|
||||
@snippets = SnippetsFinder.new.execute(current_user, {
|
||||
filter: :by_user,
|
||||
user: @user,
|
||||
scope: params[:scope]
|
||||
})
|
||||
.page(params[:page])
|
||||
@snippets = SnippetsFinder.new(current_user, author: @user, scope: params[:scope])
|
||||
.execute.page(params[:page])
|
||||
|
||||
render 'index'
|
||||
else
|
||||
|
@ -103,20 +99,20 @@ class SnippetsController < ApplicationController
|
|||
protected
|
||||
|
||||
def snippet
|
||||
@snippet ||= if current_user
|
||||
PersonalSnippet.where("author_id = ? OR visibility_level IN (?)",
|
||||
current_user.id,
|
||||
[Snippet::PUBLIC, Snippet::INTERNAL]).
|
||||
find(params[:id])
|
||||
else
|
||||
PersonalSnippet.find(params[:id])
|
||||
end
|
||||
@snippet ||= PersonalSnippet.find_by(id: params[:id])
|
||||
end
|
||||
|
||||
alias_method :awardable, :snippet
|
||||
alias_method :spammable, :snippet
|
||||
|
||||
def authorize_read_snippet!
|
||||
authenticate_user! unless can?(current_user, :read_personal_snippet, @snippet)
|
||||
return if can?(current_user, :read_personal_snippet, @snippet)
|
||||
|
||||
if current_user
|
||||
render_404
|
||||
else
|
||||
authenticate_user!
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_update_snippet!
|
||||
|
|
|
@ -128,12 +128,11 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
def load_snippets
|
||||
@snippets = SnippetsFinder.new.execute(
|
||||
@snippets = SnippetsFinder.new(
|
||||
current_user,
|
||||
filter: :by_user,
|
||||
user: user,
|
||||
author: user,
|
||||
scope: params[:scope]
|
||||
).page(params[:page])
|
||||
).execute.page(params[:page])
|
||||
end
|
||||
|
||||
def projects_for_current_user
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
class GroupsFinder < UnionFinder
|
||||
def execute(current_user = nil)
|
||||
segments = all_groups(current_user)
|
||||
def initialize(current_user = nil, params = {})
|
||||
@current_user = current_user
|
||||
@params = params
|
||||
end
|
||||
|
||||
find_union(segments, Group).with_route.order_id_desc
|
||||
def execute
|
||||
groups = find_union(all_groups, Group).with_route.order_id_desc
|
||||
by_parent(groups)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def all_groups(current_user)
|
||||
attr_reader :current_user, :params
|
||||
|
||||
def all_groups
|
||||
groups = []
|
||||
|
||||
groups << current_user.authorized_groups if current_user
|
||||
|
@ -15,4 +21,10 @@ class GroupsFinder < UnionFinder
|
|||
|
||||
groups
|
||||
end
|
||||
|
||||
def by_parent(groups)
|
||||
return groups unless params[:parent]
|
||||
|
||||
groups.where(parent: params[:parent])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -67,7 +67,7 @@ class NotesFinder
|
|||
when "merge_request"
|
||||
MergeRequestsFinder.new(@current_user, project_id: @project.id).execute
|
||||
when "snippet", "project_snippet"
|
||||
SnippetsFinder.new.execute(@current_user, filter: :by_project, project: @project)
|
||||
SnippetsFinder.new(@current_user, project: @project).execute
|
||||
when "personal_snippet"
|
||||
PersonalSnippet.all
|
||||
else
|
||||
|
|
|
@ -1,66 +1,74 @@
|
|||
class SnippetsFinder
|
||||
def execute(current_user, params = {})
|
||||
filter = params[:filter]
|
||||
user = params.fetch(:user, current_user)
|
||||
class SnippetsFinder < UnionFinder
|
||||
attr_accessor :current_user, :params
|
||||
|
||||
case filter
|
||||
when :all then
|
||||
snippets(current_user).fresh
|
||||
when :public then
|
||||
Snippet.are_public.fresh
|
||||
when :by_user then
|
||||
by_user(current_user, user, params[:scope])
|
||||
when :by_project
|
||||
by_project(current_user, params[:project], params[:scope])
|
||||
end
|
||||
def initialize(current_user, params = {})
|
||||
@current_user = current_user
|
||||
@params = params
|
||||
end
|
||||
|
||||
def execute
|
||||
items = init_collection
|
||||
items = by_project(items)
|
||||
items = by_author(items)
|
||||
items = by_visibility(items)
|
||||
|
||||
items.fresh
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def snippets(current_user)
|
||||
if current_user
|
||||
Snippet.public_and_internal
|
||||
else
|
||||
# Not authenticated
|
||||
#
|
||||
# Return only:
|
||||
# public snippets
|
||||
Snippet.are_public
|
||||
end
|
||||
def init_collection
|
||||
items = Snippet.all
|
||||
|
||||
accessible(items)
|
||||
end
|
||||
|
||||
def by_user(current_user, user, scope)
|
||||
snippets = user.snippets.fresh
|
||||
def accessible(items)
|
||||
segments = []
|
||||
segments << items.public_to_user(current_user)
|
||||
segments << authorized_to_user(items) if current_user
|
||||
|
||||
if current_user
|
||||
include_private = user == current_user
|
||||
by_scope(snippets, scope, include_private)
|
||||
else
|
||||
snippets.are_public
|
||||
end
|
||||
find_union(segments, Snippet)
|
||||
end
|
||||
|
||||
def by_project(current_user, project, scope)
|
||||
snippets = project.snippets.fresh
|
||||
|
||||
if current_user
|
||||
include_private = project.team.member?(current_user) || current_user.admin?
|
||||
by_scope(snippets, scope, include_private)
|
||||
else
|
||||
snippets.are_public
|
||||
end
|
||||
def authorized_to_user(items)
|
||||
items.where(
|
||||
'author_id = :author_id
|
||||
OR project_id IN (:project_ids)',
|
||||
author_id: current_user.id,
|
||||
project_ids: current_user.authorized_projects.select(:id))
|
||||
end
|
||||
|
||||
def by_scope(snippets, scope = nil, include_private = false)
|
||||
case scope.to_s
|
||||
def by_visibility(items)
|
||||
visibility = params[:visibility] || visibility_from_scope
|
||||
|
||||
return items unless visibility
|
||||
|
||||
items.where(visibility_level: visibility)
|
||||
end
|
||||
|
||||
def by_author(items)
|
||||
return items unless params[:author]
|
||||
|
||||
items.where(author_id: params[:author].id)
|
||||
end
|
||||
|
||||
def by_project(items)
|
||||
return items unless params[:project]
|
||||
|
||||
items.where(project_id: params[:project].id)
|
||||
end
|
||||
|
||||
def visibility_from_scope
|
||||
case params[:scope].to_s
|
||||
when 'are_private'
|
||||
include_private ? snippets.are_private : Snippet.none
|
||||
Snippet::PRIVATE
|
||||
when 'are_internal'
|
||||
snippets.are_internal
|
||||
Snippet::INTERNAL
|
||||
when 'are_public'
|
||||
snippets.are_public
|
||||
Snippet::PUBLIC
|
||||
else
|
||||
include_private ? snippets : snippets.public_and_internal
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -98,7 +98,7 @@ module DiffHelper
|
|||
[
|
||||
content_tag(:span, link_to(truncate(blob.name, length: 40), tree)),
|
||||
'@',
|
||||
content_tag(:span, commit_id, class: 'monospace'),
|
||||
content_tag(:span, commit_id, class: 'monospace')
|
||||
].join(' ').html_safe
|
||||
end
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ module EmailsHelper
|
|||
"action" => {
|
||||
"@type" => "ViewAction",
|
||||
"name" => name,
|
||||
"url" => url,
|
||||
"url" => url
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ module EventsHelper
|
|||
link_opts = {
|
||||
class: "event-filter-link",
|
||||
id: "#{key}_event_filter",
|
||||
title: "Filter by #{tooltip.downcase}",
|
||||
title: "Filter by #{tooltip.downcase}"
|
||||
}
|
||||
|
||||
content_tag :li, class: active do
|
||||
|
|
|
@ -10,7 +10,7 @@ module ExploreHelper
|
|||
personal: params[:personal],
|
||||
archived: params[:archived],
|
||||
shared: params[:shared],
|
||||
namespace_id: params[:namespace_id],
|
||||
namespace_id: params[:namespace_id]
|
||||
}
|
||||
|
||||
options = exist_opts.merge(options).delete_if { |key, value| value.blank? }
|
||||
|
|
|
@ -32,7 +32,7 @@ module MarkupHelper
|
|||
context = {
|
||||
project: @project,
|
||||
current_user: (current_user if defined?(current_user)),
|
||||
pipeline: :single_line,
|
||||
pipeline: :single_line
|
||||
}
|
||||
gfm_body = Banzai.render(body, context)
|
||||
|
||||
|
@ -116,13 +116,13 @@ module MarkupHelper
|
|||
if gitlab_markdown?(file_name)
|
||||
markdown_unsafe(text, context)
|
||||
elsif asciidoc?(file_name)
|
||||
asciidoc_unsafe(text)
|
||||
asciidoc_unsafe(text, context)
|
||||
elsif plain?(file_name)
|
||||
content_tag :pre, class: 'plain-readme' do
|
||||
text
|
||||
end
|
||||
else
|
||||
other_markup_unsafe(file_name, text)
|
||||
other_markup_unsafe(file_name, text, context)
|
||||
end
|
||||
rescue RuntimeError
|
||||
simple_format(text)
|
||||
|
@ -217,12 +217,12 @@ module MarkupHelper
|
|||
Banzai.render(text, context)
|
||||
end
|
||||
|
||||
def asciidoc_unsafe(text)
|
||||
Gitlab::Asciidoc.render(text)
|
||||
def asciidoc_unsafe(text, context = {})
|
||||
Gitlab::Asciidoc.render(text, context)
|
||||
end
|
||||
|
||||
def other_markup_unsafe(file_name, text)
|
||||
Gitlab::OtherMarkup.render(file_name, text)
|
||||
def other_markup_unsafe(file_name, text, context = {})
|
||||
Gitlab::OtherMarkup.render(file_name, text, context)
|
||||
end
|
||||
|
||||
def prepare_for_rendering(html, context = {})
|
||||
|
|
|
@ -54,7 +54,7 @@ module MergeRequestsHelper
|
|||
source_project_id: merge_request.source_project_id,
|
||||
target_project_id: merge_request.target_project_id,
|
||||
source_branch: merge_request.source_branch,
|
||||
target_branch: merge_request.target_branch,
|
||||
target_branch: merge_request.target_branch
|
||||
},
|
||||
change_branches: true
|
||||
)
|
||||
|
|
|
@ -19,7 +19,7 @@ module NotesHelper
|
|||
id: noteable.id,
|
||||
class: noteable.class.name,
|
||||
resources: noteable.class.table_name,
|
||||
project_id: noteable.project.id,
|
||||
project_id: noteable.project.id
|
||||
}.to_json
|
||||
end
|
||||
|
||||
|
@ -34,7 +34,7 @@ module NotesHelper
|
|||
|
||||
data = {
|
||||
line_code: line_code,
|
||||
line_type: line_type,
|
||||
line_type: line_type
|
||||
}
|
||||
|
||||
if @use_legacy_diff_notes
|
||||
|
|
|
@ -42,7 +42,7 @@ module SearchHelper
|
|||
{ category: "Settings", label: "User settings", url: profile_path },
|
||||
{ category: "Settings", label: "SSH Keys", url: profile_keys_path },
|
||||
{ category: "Settings", label: "Dashboard", url: root_path },
|
||||
{ category: "Settings", label: "Admin Section", url: admin_root_path },
|
||||
{ category: "Settings", label: "Admin Section", url: admin_root_path }
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -57,7 +57,7 @@ module SearchHelper
|
|||
{ category: "Help", label: "SSH Keys Help", url: help_page_path("ssh/README") },
|
||||
{ category: "Help", label: "System Hooks Help", url: help_page_path("system_hooks/system_hooks") },
|
||||
{ category: "Help", label: "Webhooks Help", url: help_page_path("user/project/integrations/webhooks") },
|
||||
{ category: "Help", label: "Workflow Help", url: help_page_path("workflow/README") },
|
||||
{ category: "Help", label: "Workflow Help", url: help_page_path("workflow/README") }
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -76,7 +76,7 @@ module SearchHelper
|
|||
{ category: "Current Project", label: "Milestones", url: namespace_project_milestones_path(@project.namespace, @project) },
|
||||
{ category: "Current Project", label: "Snippets", url: namespace_project_snippets_path(@project.namespace, @project) },
|
||||
{ category: "Current Project", label: "Members", url: namespace_project_settings_members_path(@project.namespace, @project) },
|
||||
{ category: "Current Project", label: "Wiki", url: namespace_project_wikis_path(@project.namespace, @project) },
|
||||
{ category: "Current Project", label: "Wiki", url: namespace_project_wikis_path(@project.namespace, @project) }
|
||||
]
|
||||
else
|
||||
[]
|
||||
|
|
|
@ -67,7 +67,7 @@ module SelectsHelper
|
|||
current_user: opts[:current_user] || false,
|
||||
"push-code-to-protected-branches" => opts[:push_code_to_protected_branches],
|
||||
author_id: opts[:author_id] || '',
|
||||
skip_users: opts[:skip_users] ? opts[:skip_users].map(&:id) : nil,
|
||||
skip_users: opts[:skip_users] ? opts[:skip_users].map(&:id) : nil
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -58,7 +58,7 @@ module SortingHelper
|
|||
sort_value_due_date_soon => sort_title_due_date_soon,
|
||||
sort_value_due_date_later => sort_title_due_date_later,
|
||||
sort_value_start_date_soon => sort_title_start_date_soon,
|
||||
sort_value_start_date_later => sort_title_start_date_later,
|
||||
sort_value_start_date_later => sort_title_start_date_later
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -1,28 +1,30 @@
|
|||
module SubmoduleHelper
|
||||
include Gitlab::ShellAdapter
|
||||
|
||||
VALID_SUBMODULE_PROTOCOLS = %w[http https git ssh].freeze
|
||||
|
||||
# links to files listing for submodule if submodule is a project on this server
|
||||
def submodule_links(submodule_item, ref = nil, repository = @repository)
|
||||
url = repository.submodule_url_for(ref, submodule_item.path)
|
||||
|
||||
return url, nil unless url =~ /([^\/:]+)\/([^\/]+(?:\.git)?)\Z/
|
||||
if url =~ /([^\/:]+)\/([^\/]+(?:\.git)?)\Z/
|
||||
namespace, project = $1, $2
|
||||
project.sub!(/\.git\z/, '')
|
||||
|
||||
namespace = $1
|
||||
project = $2
|
||||
project.chomp!('.git')
|
||||
|
||||
if self_url?(url, namespace, project)
|
||||
return namespace_project_path(namespace, project),
|
||||
namespace_project_tree_path(namespace, project,
|
||||
submodule_item.id)
|
||||
elsif relative_self_url?(url)
|
||||
relative_self_links(url, submodule_item.id)
|
||||
elsif github_dot_com_url?(url)
|
||||
standard_links('github.com', namespace, project, submodule_item.id)
|
||||
elsif gitlab_dot_com_url?(url)
|
||||
standard_links('gitlab.com', namespace, project, submodule_item.id)
|
||||
if self_url?(url, namespace, project)
|
||||
[namespace_project_path(namespace, project),
|
||||
namespace_project_tree_path(namespace, project, submodule_item.id)]
|
||||
elsif relative_self_url?(url)
|
||||
relative_self_links(url, submodule_item.id)
|
||||
elsif github_dot_com_url?(url)
|
||||
standard_links('github.com', namespace, project, submodule_item.id)
|
||||
elsif gitlab_dot_com_url?(url)
|
||||
standard_links('gitlab.com', namespace, project, submodule_item.id)
|
||||
else
|
||||
[sanitize_submodule_url(url), nil]
|
||||
end
|
||||
else
|
||||
return url, nil
|
||||
[sanitize_submodule_url(url), nil]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -73,4 +75,16 @@ module SubmoduleHelper
|
|||
namespace_project_tree_path(namespace, base, commit)
|
||||
]
|
||||
end
|
||||
|
||||
def sanitize_submodule_url(url)
|
||||
uri = URI.parse(url)
|
||||
|
||||
if uri.scheme.in?(VALID_SUBMODULE_PROTOCOLS)
|
||||
uri.to_s
|
||||
else
|
||||
nil
|
||||
end
|
||||
rescue URI::InvalidURIError
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -63,7 +63,7 @@ module TodosHelper
|
|||
project_id: params[:project_id],
|
||||
author_id: params[:author_id],
|
||||
type: params[:type],
|
||||
action_id: params[:action_id],
|
||||
action_id: params[:action_id]
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class Blob < SimpleDelegator
|
|||
BlobViewer::PDF,
|
||||
|
||||
BlobViewer::BinarySTL,
|
||||
BlobViewer::TextSTL,
|
||||
BlobViewer::TextSTL
|
||||
].freeze
|
||||
|
||||
BINARY_VIEWERS = RICH_VIEWERS.select(&:binary?).freeze
|
||||
|
|
|
@ -124,8 +124,8 @@ module Ci
|
|||
success? || failed? || canceled?
|
||||
end
|
||||
|
||||
def retried?
|
||||
!self.pipeline.statuses.latest.include?(self)
|
||||
def latest?
|
||||
!retried?
|
||||
end
|
||||
|
||||
def expanded_environment_name
|
||||
|
|
|
@ -49,7 +49,7 @@ class Commit
|
|||
def max_diff_options
|
||||
{
|
||||
max_files: DIFF_HARD_LIMIT_FILES,
|
||||
max_lines: DIFF_HARD_LIMIT_LINES,
|
||||
max_lines: DIFF_HARD_LIMIT_LINES
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -18,13 +18,7 @@ class CommitStatus < ActiveRecord::Base
|
|||
validates :name, presence: true
|
||||
|
||||
alias_attribute :author, :user
|
||||
|
||||
scope :latest, -> do
|
||||
max_id = unscope(:select).select("max(#{quoted_table_name}.id)")
|
||||
|
||||
where(id: max_id.group(:name, :commit_id))
|
||||
end
|
||||
|
||||
|
||||
scope :failed_but_allowed, -> do
|
||||
where(allow_failure: true, status: [:failed, :canceled])
|
||||
end
|
||||
|
@ -37,7 +31,8 @@ class CommitStatus < ActiveRecord::Base
|
|||
false, all_state_names - [:failed, :canceled, :manual])
|
||||
end
|
||||
|
||||
scope :retried, -> { where.not(id: latest) }
|
||||
scope :latest, -> { where(retried: [false, nil]) }
|
||||
scope :retried, -> { where(retried: true) }
|
||||
scope :ordered, -> { order(:name) }
|
||||
scope :latest_ordered, -> { latest.ordered.includes(project: :namespace) }
|
||||
scope :retried_ordered, -> { retried.ordered.includes(project: :namespace) }
|
||||
|
|
|
@ -39,7 +39,7 @@ class DiffDiscussion < Discussion
|
|||
def reply_attributes
|
||||
super.merge(
|
||||
original_position: original_position.to_json,
|
||||
position: position.to_json,
|
||||
position: position.to_json
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -62,7 +62,7 @@ class Environment < ActiveRecord::Base
|
|||
def predefined_variables
|
||||
[
|
||||
{ key: 'CI_ENVIRONMENT_NAME', value: name, public: true },
|
||||
{ key: 'CI_ENVIRONMENT_SLUG', value: slug, public: true },
|
||||
{ key: 'CI_ENVIRONMENT_SLUG', value: slug, public: true }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class WebHook < ActiveRecord::Base
|
|||
post_url = url.gsub("#{parsed_url.userinfo}@", '')
|
||||
auth = {
|
||||
username: CGI.unescape(parsed_url.user),
|
||||
password: CGI.unescape(parsed_url.password),
|
||||
password: CGI.unescape(parsed_url.password)
|
||||
}
|
||||
response = WebHook.post(post_url,
|
||||
body: data.to_json,
|
||||
|
|
|
@ -74,7 +74,7 @@ class Key < ActiveRecord::Base
|
|||
GitlabShellWorker.perform_async(
|
||||
:remove_key,
|
||||
shell_id,
|
||||
key,
|
||||
key
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ class Namespace < ActiveRecord::Base
|
|||
'COALESCE(SUM(ps.storage_size), 0) AS storage_size',
|
||||
'COALESCE(SUM(ps.repository_size), 0) AS repository_size',
|
||||
'COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size',
|
||||
'COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size',
|
||||
'COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size'
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -967,7 +967,7 @@ class Project < ActiveRecord::Base
|
|||
namespace: namespace.name,
|
||||
visibility_level: visibility_level,
|
||||
path_with_namespace: path_with_namespace,
|
||||
default_branch: default_branch,
|
||||
default_branch: default_branch
|
||||
}
|
||||
|
||||
# Backward compatibility
|
||||
|
|
|
@ -52,7 +52,7 @@ class BambooService < CiService
|
|||
placeholder: 'Bamboo build plan key like KEY' },
|
||||
{ type: 'text', name: 'username',
|
||||
placeholder: 'A user with API access, if applicable' },
|
||||
{ type: 'password', name: 'password' },
|
||||
{ type: 'password', name: 'password' }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ class ChatNotificationService < Service
|
|||
{ type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" },
|
||||
{ type: 'text', name: 'username', placeholder: 'e.g. GitLab' },
|
||||
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
|
||||
{ type: 'checkbox', name: 'notify_only_default_branch' },
|
||||
{ type: 'checkbox', name: 'notify_only_default_branch' }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ class EmailsOnPushService < Service
|
|||
help: "Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. #{domains})." },
|
||||
{ type: 'checkbox', name: 'disable_diffs', title: "Disable code diffs",
|
||||
help: "Don't include possibly sensitive code diffs in notification body." },
|
||||
{ type: 'textarea', name: 'recipients', placeholder: 'Emails separated by whitespace' },
|
||||
{ type: 'textarea', name: 'recipients', placeholder: 'Emails separated by whitespace' }
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,7 +19,7 @@ class ExternalWikiService < Service
|
|||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'external_wiki_url', placeholder: 'The URL of the external Wiki' },
|
||||
{ type: 'text', name: 'external_wiki_url', placeholder: 'The URL of the external Wiki' }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ class FlowdockService < Service
|
|||
repo: project.repository.path_to_repo,
|
||||
repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}",
|
||||
commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s",
|
||||
diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s",
|
||||
diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,7 +41,7 @@ class HipchatService < Service
|
|||
placeholder: 'Leave blank for default (v2)' },
|
||||
{ type: 'text', name: 'server',
|
||||
placeholder: 'Leave blank for default. https://hipchat.example.com' },
|
||||
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
|
||||
{ type: 'checkbox', name: 'notify_only_broken_pipelines' }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ class IrkerService < Service
|
|||
' want to use a password, you have to omit the "#" on the channel). If you ' \
|
||||
' specify a default IRC URI to prepend before each recipient, you can just ' \
|
||||
' give a channel name.' },
|
||||
{ type: 'checkbox', name: 'colorize_messages' },
|
||||
{ type: 'checkbox', name: 'colorize_messages' }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ class JiraService < IssueTrackerService
|
|||
data = {
|
||||
user: {
|
||||
name: author.name,
|
||||
url: resource_url(user_path(author)),
|
||||
url: resource_url(user_path(author))
|
||||
},
|
||||
project: {
|
||||
name: self.project.path_with_namespace,
|
||||
|
|
|
@ -73,7 +73,7 @@ class KubernetesService < DeploymentService
|
|||
{ type: 'textarea',
|
||||
name: 'ca_pem',
|
||||
title: 'Custom CA bundle',
|
||||
placeholder: 'Certificate Authority bundle (PEM format)' },
|
||||
placeholder: 'Certificate Authority bundle (PEM format)' }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class MicrosoftTeamsService < ChatNotificationService
|
|||
[
|
||||
{ type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" },
|
||||
{ type: 'checkbox', name: 'notify_only_broken_pipelines' },
|
||||
{ type: 'checkbox', name: 'notify_only_default_branch' },
|
||||
{ type: 'checkbox', name: 'notify_only_default_branch' }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class MockCiService < CiService
|
|||
[
|
||||
{ type: 'text',
|
||||
name: 'mock_service_url',
|
||||
placeholder: 'http://localhost:4004' },
|
||||
placeholder: 'http://localhost:4004' }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ class PipelinesEmailService < Service
|
|||
name: 'recipients',
|
||||
placeholder: 'Emails separated by comma' },
|
||||
{ type: 'checkbox',
|
||||
name: 'notify_only_broken_pipelines' },
|
||||
name: 'notify_only_broken_pipelines' }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ class PushoverService < Service
|
|||
['Pushover Echo (long)', 'echo'],
|
||||
['Up Down (long)', 'updown'],
|
||||
['None (silent)', 'none']
|
||||
] },
|
||||
] }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ class TeamcityService < CiService
|
|||
placeholder: 'Build configuration ID' },
|
||||
{ type: 'text', name: 'username',
|
||||
placeholder: 'A user with permissions to trigger a manual build' },
|
||||
{ type: 'password', name: 'password' },
|
||||
{ type: 'password', name: 'password' }
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -78,7 +78,7 @@ class TeamcityService < CiService
|
|||
|
||||
auth = {
|
||||
username: username,
|
||||
password: password,
|
||||
password: password
|
||||
}
|
||||
|
||||
branch = Gitlab::Git.ref_name(data[:ref])
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
class ReadmeBlob < SimpleDelegator
|
||||
attr_reader :repository
|
||||
|
||||
def initialize(blob, repository)
|
||||
@repository = repository
|
||||
|
||||
super(blob)
|
||||
end
|
||||
|
||||
def rendered_markup
|
||||
repository.rendered_readme
|
||||
end
|
||||
end
|
|
@ -518,7 +518,7 @@ class Repository
|
|||
|
||||
def readme
|
||||
if head = tree(:head)
|
||||
head.readme
|
||||
ReadmeBlob.new(head.readme, self)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -833,7 +833,7 @@ class Repository
|
|||
|
||||
actual_options = options.merge(
|
||||
parents: [our_commit, their_commit],
|
||||
tree: merge_index.write_tree(rugged),
|
||||
tree: merge_index.write_tree(rugged)
|
||||
)
|
||||
|
||||
commit_id = create_commit(actual_options)
|
||||
|
|
|
@ -39,7 +39,7 @@ class SentNotification < ActiveRecord::Base
|
|||
|
||||
noteable_type: noteable.class.name,
|
||||
noteable_id: noteable_id,
|
||||
commit_id: commit_id,
|
||||
commit_id: commit_id
|
||||
)
|
||||
|
||||
create(attrs)
|
||||
|
|
|
@ -152,18 +152,5 @@ class Snippet < ActiveRecord::Base
|
|||
|
||||
where(table[:content].matches(pattern))
|
||||
end
|
||||
|
||||
def accessible_to(user)
|
||||
return are_public unless user.present?
|
||||
return all if user.admin?
|
||||
|
||||
where(
|
||||
'visibility_level IN (:visibility_levels)
|
||||
OR author_id = :author_id
|
||||
OR project_id IN (:project_ids)',
|
||||
visibility_levels: [Snippet::PUBLIC, Snippet::INTERNAL],
|
||||
author_id: user.id,
|
||||
project_ids: user.authorized_projects.select(:id))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,10 +40,7 @@ class Tree
|
|||
|
||||
readme_path = path == '/' ? readme_tree.name : File.join(path, readme_tree.name)
|
||||
|
||||
git_repo = repository.raw_repository
|
||||
@readme = Gitlab::Git::Blob.find(git_repo, sha, readme_path)
|
||||
@readme.load_all_data!(git_repo)
|
||||
@readme
|
||||
@readme = repository.blob_at(sha, readme_path)
|
||||
end
|
||||
|
||||
def trees
|
||||
|
|
|
@ -13,7 +13,7 @@ class ProjectSnippetPolicy < BasePolicy
|
|||
can! :read_project_snippet
|
||||
end
|
||||
|
||||
if @subject.private? && @subject.project.team.member?(@user)
|
||||
if @subject.project.team.member?(@user)
|
||||
can! :read_project_snippet
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,7 +16,7 @@ class AkismetService
|
|||
created_at: DateTime.now,
|
||||
author: owner.name,
|
||||
author_email: owner.email,
|
||||
referrer: options[:referrer],
|
||||
referrer: options[:referrer]
|
||||
}
|
||||
|
||||
begin
|
||||
|
|
|
@ -8,7 +8,7 @@ class AuditEventService
|
|||
with: @details[:with],
|
||||
target_id: @author.id,
|
||||
target_type: 'User',
|
||||
target_details: @author.name,
|
||||
target_details: @author.name
|
||||
}
|
||||
|
||||
self
|
||||
|
|
|
@ -38,7 +38,7 @@ module Boards
|
|||
attrs.merge!(
|
||||
add_label_ids: add_label_ids,
|
||||
remove_label_ids: remove_label_ids,
|
||||
state_event: issue_state,
|
||||
state_event: issue_state
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ module Ci
|
|||
def execute(pipeline)
|
||||
@pipeline = pipeline
|
||||
|
||||
update_retried
|
||||
|
||||
new_builds =
|
||||
stage_indexes_of_created_builds.map do |index|
|
||||
process_stage(index)
|
||||
|
@ -71,5 +73,23 @@ module Ci
|
|||
def created_builds
|
||||
pipeline.builds.created
|
||||
end
|
||||
|
||||
# This method is for compatibility and data consistency and should be removed with 9.3 version of GitLab
|
||||
# This replicates what is db/post_migrate/20170416103934_upate_retried_for_ci_build.rb
|
||||
# and ensures that functionality will not be broken before migration is run
|
||||
# this updates only when there are data that needs to be updated, there are two groups with no retried flag
|
||||
def update_retried
|
||||
# find the latest builds for each name
|
||||
latest_statuses = pipeline.statuses.latest
|
||||
.group(:name)
|
||||
.having('count(*) > 1')
|
||||
.pluck('max(id)', 'name')
|
||||
|
||||
# mark builds that are retried
|
||||
pipeline.statuses.latest
|
||||
.where(name: latest_statuses.map(&:second))
|
||||
.where.not(id: latest_statuses.map(&:first))
|
||||
.update_all(retried: true) if latest_statuses.any?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,7 +6,7 @@ module Ci
|
|||
description tag_list].freeze
|
||||
|
||||
def execute(build)
|
||||
reprocess(build).tap do |new_build|
|
||||
reprocess!(build).tap do |new_build|
|
||||
build.pipeline.mark_as_processable_after_stage(build.stage_idx)
|
||||
|
||||
new_build.enqueue!
|
||||
|
@ -17,7 +17,7 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
def reprocess(build)
|
||||
def reprocess!(build)
|
||||
unless can?(current_user, :update_build, build)
|
||||
raise Gitlab::Access::AccessDeniedError
|
||||
end
|
||||
|
@ -28,7 +28,14 @@ module Ci
|
|||
|
||||
attributes.push([:user, current_user])
|
||||
|
||||
project.builds.create(Hash[attributes])
|
||||
Ci::Build.transaction do
|
||||
# mark all other builds of that name as retried
|
||||
build.pipeline.builds.latest
|
||||
.where(name: build.name)
|
||||
.update_all(retried: true)
|
||||
|
||||
project.builds.create!(Hash[attributes])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,7 +11,7 @@ module Ci
|
|||
next unless can?(current_user, :update_build, build)
|
||||
|
||||
Ci::RetryBuildService.new(project, current_user)
|
||||
.reprocess(build)
|
||||
.reprocess!(build)
|
||||
end
|
||||
|
||||
pipeline.builds.latest.skipped.find_each do |skipped|
|
||||
|
|
|
@ -298,7 +298,7 @@ class NotificationService
|
|||
recipients ||= NotificationRecipientService.new(pipeline.project).build_pipeline_recipients(
|
||||
pipeline,
|
||||
pipeline.user,
|
||||
action: pipeline.status,
|
||||
action: pipeline.status
|
||||
).map(&:notification_email)
|
||||
|
||||
if recipients.any?
|
||||
|
|
|
@ -27,7 +27,7 @@ module Projects
|
|||
{
|
||||
domain: domain.domain,
|
||||
certificate: domain.certificate,
|
||||
key: domain.key,
|
||||
key: domain.key
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ module Search
|
|||
end
|
||||
|
||||
def execute
|
||||
snippets = Snippet.accessible_to(current_user)
|
||||
snippets = SnippetsFinder.new(current_user).execute
|
||||
|
||||
Gitlab::SnippetSearchResults.new(snippets, params[:search])
|
||||
end
|
||||
|
|
|
@ -51,7 +51,7 @@ class SystemHooksService
|
|||
path: model.path,
|
||||
group_id: model.id,
|
||||
owner_name: owner.respond_to?(:name) ? owner.name : nil,
|
||||
owner_email: owner.respond_to?(:email) ? owner.email : nil,
|
||||
owner_email: owner.respond_to?(:email) ? owner.email : nil
|
||||
)
|
||||
when GroupMember
|
||||
data.merge!(group_member_data(model))
|
||||
|
@ -113,7 +113,7 @@ class SystemHooksService
|
|||
user_name: model.user.name,
|
||||
user_email: model.user.email,
|
||||
user_id: model.user.id,
|
||||
group_access: model.human_access,
|
||||
group_access: model.human_access
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
.diff-file.file-holder
|
||||
.js-file-title.file-title
|
||||
= render "projects/diffs/file_header", diff_file: diff_file, blob: blob, diff_commit: diff_file.content_commit, project: discussion.project, url: discussion_path(discussion)
|
||||
= render "projects/diffs/file_header", diff_file: diff_file, blob: blob, diff_commit: diff_file.content_commit, project: discussion.project, url: discussion_path(discussion), show_toggle: false
|
||||
|
||||
.diff-content.code.js-syntax-highlight
|
||||
%table
|
||||
|
|
|
@ -10,4 +10,4 @@
|
|||
- else
|
||||
:plain
|
||||
job = $("tr#repo_#{@repo_id}")
|
||||
job.find(".import-actions").html("<i class='fa fa-exclamation-circle'></i> Error saving project: #{escape_javascript(@project.errors.full_messages.join(','))}")
|
||||
job.find(".import-actions").html("<i class='fa fa-exclamation-circle'></i> Error saving project: #{escape_javascript(h(@project.errors.full_messages.join(',')))}")
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
%article.readme-holder
|
||||
.pull-right
|
||||
- if can?(current_user, :push_code, @project)
|
||||
= link_to icon('pencil'), namespace_project_edit_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)), class: 'light edit-project-readme'
|
||||
.file-content.wiki
|
||||
= markup(readme.name, readme.data, rendered: @repository.rendered_readme)
|
||||
= link_to icon('pencil'), namespace_project_edit_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.path)), class: 'light edit-project-readme'
|
||||
|
||||
= render 'projects/blob/viewer', viewer: readme.rich_viewer, viewer_url: namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.path), viewer: :rich, format: :json)
|
||||
- else
|
||||
.row-content-block.second-block.center
|
||||
%h3.page-title
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
- @gfm_form = true
|
||||
- current_text ||= nil
|
||||
- supports_slash_commands = local_assigns.fetch(:supports_slash_commands, false)
|
||||
.zen-backdrop
|
||||
- classes << ' js-gfm-input js-autosize markdown-area'
|
||||
- if defined?(f) && f
|
||||
= f.text_area attr, class: classes, placeholder: placeholder, data: { supports_slash_commands: supports_slash_commands }
|
||||
- else
|
||||
= text_area_tag attr, nil, class: classes, placeholder: placeholder
|
||||
= text_area_tag attr, current_text, class: classes, placeholder: placeholder
|
||||
%a.zen-control.zen-control-leave.js-zen-leave{ href: "#" }
|
||||
= icon('compress')
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
- render_error = viewer.render_error
|
||||
- load_asynchronously = local_assigns.fetch(:load_asynchronously, viewer.server_side?) && render_error.nil?
|
||||
|
||||
- url = url_for(params.merge(viewer: viewer.type, format: :json)) if load_asynchronously
|
||||
.blob-viewer{ data: { type: viewer.type, url: url }, class: ('hidden' if hidden) }
|
||||
- viewer_url = local_assigns.fetch(:viewer_url) { url_for(params.merge(viewer: viewer.type, format: :json)) } if load_asynchronously
|
||||
.blob-viewer{ data: { type: viewer.type, url: viewer_url }, class: ('hidden' if hidden) }
|
||||
- if load_asynchronously
|
||||
.text-center.prepend-top-default.append-bottom-default
|
||||
= icon('spinner spin 2x', 'aria-hidden' => 'true', 'aria-label' => 'Loading content')
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
name: "issue[milestone_id]",
|
||||
"v-if" => "issue.milestone" }
|
||||
.dropdown
|
||||
%button.dropdown-menu-toggle.js-milestone-select.js-issue-board-sidebar{ type: "button", data: { toggle: "dropdown", show_no: "true", field_name: "issue[milestone_id]", project_id: @project.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :json), ability_name: "issue", use_id: "true" },
|
||||
%button.dropdown-menu-toggle.js-milestone-select.js-issue-board-sidebar{ type: "button", data: { toggle: "dropdown", show_no: "true", field_name: "issue[milestone_id]", project_id: @project.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :json), ability_name: "issue", use_id: "true", default_no: "true" },
|
||||
":data-selected" => "milestoneTitle",
|
||||
":data-issuable-id" => "issue.id",
|
||||
":data-issue-update" => "'#{namespace_project_issues_path(@project.namespace, @project)}/' + issue.id + '.json'" }
|
||||
Milestone
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
%ul
|
||||
%li.stage-header
|
||||
%span.stage-name
|
||||
{{ __('ProjectLifecycle|Stage') }}
|
||||
{{ s__('ProjectLifecycle|Stage') }}
|
||||
%i.has-tooltip.fa.fa-question-circle{ "data-placement" => "top", title: _("The phase of the development lifecycle."), "aria-hidden" => "true" }
|
||||
%li.median-header
|
||||
%span.stage-name
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
%i.fa.diff-toggle-caret.fa-fw
|
||||
- show_toggle = local_assigns.fetch(:show_toggle, true)
|
||||
|
||||
- if show_toggle
|
||||
%i.fa.diff-toggle-caret.fa-fw
|
||||
|
||||
- if defined?(blob) && blob && diff_file.submodule?
|
||||
%span
|
||||
= icon('archive fw')
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
.panel-body
|
||||
%pre
|
||||
:preserve
|
||||
#{sanitize_repo_path(@project, @project.import_error)}
|
||||
#{h(sanitize_repo_path(@project, @project.import_error))}
|
||||
|
||||
= form_for @project, url: namespace_project_import_path(@project.namespace, @project), method: :post, html: { class: 'form-horizontal' } do |f|
|
||||
= render "shared/import_form", f: f
|
||||
|
|
|
@ -22,14 +22,14 @@
|
|||
.form-group
|
||||
= label_tag :message, nil, class: 'control-label'
|
||||
.col-sm-10
|
||||
= text_area_tag :message, nil, required: false, tabindex: 3, class: 'form-control', rows: 5
|
||||
= text_area_tag :message, @message, required: false, tabindex: 3, class: 'form-control', rows: 5
|
||||
.help-block Optionally, add a message to the tag.
|
||||
%hr
|
||||
.form-group
|
||||
= label_tag :release_description, 'Release notes', class: 'control-label'
|
||||
.col-sm-10
|
||||
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do
|
||||
= render 'projects/zen', attr: :release_description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here..."
|
||||
= render 'projects/zen', attr: :release_description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here...", current_text: @release_description
|
||||
= render 'shared/notes/hints'
|
||||
.help-block Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page.
|
||||
.form-actions
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
%article.file-holder.readme-holder
|
||||
.js-file-title.file-title
|
||||
= blob_icon readme.mode, readme.name
|
||||
= link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@ref, @path, readme.name)) do
|
||||
= link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@ref, readme.path)) do
|
||||
%strong
|
||||
= readme.name
|
||||
.file-content.wiki
|
||||
= markup(readme.name, readme.data)
|
||||
|
||||
= render 'projects/blob/viewer', viewer: readme.rich_viewer, viewer_url: namespace_project_blob_path(@project.namespace, @project, tree_join(@ref, readme.path), viewer: :rich, format: :json)
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
%h3 Clone your wiki
|
||||
%pre.dark
|
||||
:preserve
|
||||
git clone #{ content_tag(:span, default_url_to_repo(@project_wiki), class: 'clone')}
|
||||
git clone #{ content_tag(:span, h(default_url_to_repo(@project_wiki)), class: 'clone')}
|
||||
cd #{h @project_wiki.path}
|
||||
|
||||
%h3 Start Gollum and edit locally
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
- has_button = button_path || project_select_button
|
||||
|
||||
.row.empty-state
|
||||
.pull-right.col-xs-12{ class: "#{'col-sm-6' if has_button}" }
|
||||
.col-xs-12
|
||||
.svg-content
|
||||
= render 'shared/empty_states/icons/issues.svg'
|
||||
.col-xs-12{ class: "#{'col-sm-6' if has_button}" }
|
||||
.col-xs-12.text-center
|
||||
.text-content
|
||||
- if has_button && current_user
|
||||
%h4
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.row.empty-state.labels
|
||||
.pull-right.col-xs-12.col-sm-6
|
||||
.col-xs-12
|
||||
.svg-content
|
||||
= render 'shared/empty_states/icons/labels.svg'
|
||||
.col-xs-12.col-sm-6
|
||||
.col-xs-12.text-center
|
||||
.text-content
|
||||
%h4 Labels can be applied to issues and merge requests to categorize them.
|
||||
%p You can also star a label to make it a priority label.
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
- has_button = button_path || project_select_button
|
||||
|
||||
.row.empty-state.merge-requests
|
||||
.col-xs-12{ class: "#{'col-sm-6 pull-right' if has_button}" }
|
||||
.col-xs-12
|
||||
.svg-content
|
||||
= render 'shared/empty_states/icons/merge_requests.svg'
|
||||
.col-xs-12{ class: "#{'col-sm-6' if has_button}" }
|
||||
.col-xs-12.text-center
|
||||
.text-content
|
||||
- if has_button
|
||||
%h4
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
- if selected.present? || params[:milestone_title].present?
|
||||
= hidden_field_tag(name, name == :milestone_title ? selected_text : selected.id)
|
||||
= dropdown_tag(milestone_dropdown_label(selected_text), options: { title: dropdown_title, toggle_class: "js-milestone-select js-filter-submit #{extra_class}", filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone",
|
||||
placeholder: "Search milestones", footer_content: project.present?, data: { show_no: true, show_menu_above: show_menu_above, show_any: show_any, show_upcoming: show_upcoming, show_started: show_started, field_name: name, selected: selected.try(:title), project_id: project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do
|
||||
placeholder: "Search milestones", footer_content: project.present?, data: { show_no: true, show_menu_above: show_menu_above, show_any: show_any, show_upcoming: show_upcoming, show_started: show_started, field_name: name, selected: selected_text, project_id: project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do
|
||||
- if project
|
||||
%ul.dropdown-footer-list
|
||||
- if can? current_user, :admin_milestone, project
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue