Commit 88a90bb1 authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ee

parents d071ac92 09cdabd2
......@@ -8,4 +8,4 @@
karma.config.js
webpack.config.js
svg.config.js
/app/assets/javascripts/locale/**/*.js
/app/assets/javascripts/locale/**/app.js
......@@ -85,6 +85,8 @@ entry.
- [FIXED] Fixed merge request changes bar jumping.
- [FIXED] Improve migrations using triggers.
- [FIXED] Fix ConvDev Index nav item and Monitoring submenu regression.
- [FIXED] disabling notifications globally now properly turns off group/project added
emails !13325
- [DEPRECATED] Deprecate custom SSH client configuration for the git user. !13930
- [CHANGED] allow all users to delete their account. !13636 (Jacopo Beschi @jacopo-beschi)
- [CHANGED] Use full path of project's avatar in webhooks. !13649 (Vitaliy @blackst0ne Klachkov)
......
......@@ -414,7 +414,7 @@ group :ed25519 do
end
# Gitaly GRPC client
gem 'gitaly-proto', '~> 0.33.0', require: 'gitaly'
gem 'gitaly-proto', '~> 0.38.0', require: 'gitaly'
gem 'toml-rb', '~> 0.3.15', require: false
......
......@@ -299,7 +299,7 @@ GEM
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
gherkin-ruby (0.3.2)
gitaly-proto (0.33.0)
gitaly-proto (0.38.0)
google-protobuf (~> 3.1)
grpc (~> 1.0)
github-linguist (4.7.6)
......@@ -1060,7 +1060,7 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0)
gitaly-proto (~> 0.33.0)
gitaly-proto (~> 0.38.0)
github-linguist (~> 4.7.0)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-license (~> 1.0)
......
......@@ -40,10 +40,10 @@ export default () => {
class="text-center"
v-if="error">
<span v-if="loadError">
An error occured whilst loading the file. Please try again later.
An error occurred whilst loading the file. Please try again later.
</span>
<span v-else>
An error occured whilst parsing the file.
An error occurred whilst parsing the file.
</span>
</p>
</div>
......
......@@ -48,10 +48,10 @@ export default () => {
class="text-center"
v-if="error">
<span v-if="loadError">
An error occured whilst loading the file. Please try again later.
An error occurred whilst loading the file. Please try again later.
</span>
<span v-else>
An error occured whilst decoding the file.
An error occurred whilst decoding the file.
</span>
</p>
</div>
......
......@@ -96,7 +96,7 @@ export default {
<div class="flash-container"
v-if="error">
<div class="flash-alert">
An error occured. Please try again.
An error occurred. Please try again.
</div>
</div>
<label class="label-light"
......
......@@ -167,7 +167,7 @@ window.Build = (function () {
Build.prototype.getBuildTrace = function () {
return $.ajax({
url: `${this.pageUrl}/trace.json`,
data: this.state,
data: { state: this.state },
})
.done((log) => {
setCiStatusFavicon(`${this.pageUrl}/status.json`);
......
......@@ -191,7 +191,7 @@ export default {
this.service.postAction(endpoint)
.then(() => this.fetchEnvironments())
.catch(() => new Flash('An error occured while making the request.'));
.catch(() => new Flash('An error occurred while making the request.'));
}
},
......
......@@ -170,7 +170,7 @@ export default {
this.service.postAction(endpoint)
.then(() => this.fetchEnvironments())
.catch(() => new Flash('An error occured while making the request.'));
.catch(() => new Flash('An error occurred while making the request.'));
}
},
},
......
......@@ -7,6 +7,8 @@
* causes reflows, visit https://gist.github.com/paulirish/5d52fb081b3570c81e3a
*/
import Cookies from 'js-cookie';
const LINE_NUMBER_CLASS = 'diff-line-num';
const UNFOLDABLE_LINE_CLASS = 'js-unfold';
const NO_COMMENT_CLASS = 'no-comment-btn';
......@@ -27,9 +29,7 @@ export default {
this.userCanCreateNote = $diffFile.closest(DIFF_CONTAINER_SELECTOR).data('can-create-note') === '';
}
if (typeof notes !== 'undefined' && !this.isParallelView) {
this.isParallelView = notes.isParallelView && notes.isParallelView();
}
this.isParallelView = Cookies.get('diff_view') === 'parallel';
if (this.userCanCreateNote) {
$diffFile.on('mouseover', LINE_COLUMN_CLASSES, e => this.showButton(this.isParallelView, e))
......
......@@ -14,7 +14,7 @@ class DropdownEmoji extends gl.FilteredSearchDropdown {
loadingTemplate: this.loadingTemplate,
onError() {
/* eslint-disable no-new */
new Flash('An error occured fetching the dropdown data.');
new Flash('An error occurred fetching the dropdown data.');
/* eslint-enable no-new */
},
},
......
......@@ -17,7 +17,7 @@ class DropdownNonUser extends gl.FilteredSearchDropdown {
preprocessing,
onError() {
/* eslint-disable no-new */
new Flash('An error occured fetching the dropdown data.');
new Flash('An error occurred fetching the dropdown data.');
/* eslint-enable no-new */
},
},
......
......@@ -27,7 +27,7 @@ class DropdownUser extends gl.FilteredSearchDropdown {
},
onError() {
/* eslint-disable no-new */
new Flash('An error occured fetching the dropdown data.');
new Flash('An error occurred fetching the dropdown data.');
/* eslint-enable no-new */
},
},
......
......@@ -44,7 +44,7 @@ class FilteredSearchManager {
.catch((error) => {
if (error.name === 'RecentSearchesServiceError') return undefined;
// eslint-disable-next-line no-new
new window.Flash('An error occured while parsing recent searches');
new window.Flash('An error occurred while parsing recent searches');
// Gracefully fail to empty array
return [];
})
......
......@@ -16,9 +16,8 @@ const locales = allLocales.reduce((d, obj) => {
return data;
}, {});
let lang = document.querySelector('html').getAttribute('lang') || 'en';
lang = lang.replace(/-/g, '_');
const langAttribute = document.querySelector('html').getAttribute('lang');
const lang = (langAttribute || 'en').replace(/-/g, '_');
const locale = new Jed(locales[lang]);
/**
......
......@@ -311,7 +311,10 @@ $(function () {
return $container.remove();
// Commit show suppressed diff
});
$('.navbar-toggle').on('click', () => $('.header-content').toggleClass('menu-expanded'));
$('.navbar-toggle').on('click', () => {
$('.header-content').toggleClass('menu-expanded');
gl.lazyLoader.loadCheck();
});
// Show/hide comments on diff
$body.on('click', '.js-toggle-diff-comments', function (e) {
var $this = $(this);
......
......@@ -97,7 +97,7 @@ export default {
postAction(endpoint) {
this.service.postAction(endpoint)
.then(() => eventHub.$emit('refreshPipelines'))
.catch(() => new Flash('An error occured while making the request.'));
.catch(() => new Flash('An error occurred while making the request.'));
},
},
};
......@@ -73,7 +73,8 @@ import _ from 'underscore';
aspectRatio: 1,
modal: true,
scalable: false,
rotatable: false,
rotatable: true,
checkOrientation: true,
zoomable: true,
dragMode: 'move',
guides: false,
......
......@@ -37,14 +37,14 @@ export default {
content: f.newContent,
}));
const payload = {
branch: Store.targetBranch,
branch: Store.currentBranch,
commit_message: commitMessage,
actions,
};
Store.submitCommitsLoading = true;
Service.commitFiles(payload)
.then(this.resetCommitState)
.catch(() => Flash('An error occured while committing your changes'));
.catch(() => Flash('An error occurred while committing your changes'));
},
resetCommitState() {
......@@ -105,7 +105,7 @@ export default {
</label>
<div class="col-md-6">
<span class="help-block">
{{targetBranch}}
{{currentBranch}}
</span>
</div>
</div>
......
......@@ -26,16 +26,6 @@ export default {
this.editMode = !this.editMode;
Store.toggleBlobView();
},
toggleProjectRefsForm() {
$('.project-refs-form').toggleClass('disabled', this.editMode);
$('.js-tree-ref-target-holder').toggle(this.editMode);
},
},
watch: {
editMode() {
this.toggleProjectRefsForm();
},
},
};
</script>
......
......@@ -49,7 +49,7 @@ export default {
v-else
class="vertical-center render-error">
<p class="text-center">
The source could not be displayed because a rendering error occured. You can <a :href="activeFile.raw_path">download</a> it instead.
The source could not be displayed because a rendering error occurred. You can <a :href="activeFile.raw_path">download</a> it instead.
</p>
</div>
</div>
......
......@@ -37,17 +37,24 @@ export default {
let file = clickedFile;
if (file.loading) return;
file.loading = true;
if (file.type === 'tree' && file.opened) {
file = Store.removeChildFilesOfTree(file);
file.loading = false;
} else {
Service.url = file.url;
Helper.getContent(file)
.then(() => {
file.loading = false;
Helper.scrollTabsRight();
})
.catch(Helper.loadingError);
const openFile = Helper.getFileFromPath(file.url);
if (openFile) {
file.loading = false;
Store.setActiveFiles(openFile);
} else {
Service.url = file.url;
Helper.getContent(file)
.then(() => {
file.loading = false;
Helper.scrollTabsRight();
})
.catch(Helper.loadingError);
}
}
},
......
......@@ -263,6 +263,10 @@ const RepoHelper = {
return Store.openedFiles.find(openedFile => Store.activeFile.url === openedFile.url);
},
getFileFromPath(path) {
return Store.openedFiles.find(file => file.url === path);
},
loadingError() {
Flash('Unable to load this content at this time.');
},
......
......@@ -11,10 +11,6 @@ function initDropdowns() {
}
function addEventsForNonVueEls() {
$(document).on('change', '.dropdown', () => {
Store.targetBranch = $('.project-refs-target-form input[name="ref"]').val();
});
window.onbeforeunload = function confirmUnload(e) {
const hasChanged = Store.openedFiles
.some(file => file.changed);
......
......@@ -32,7 +32,6 @@ const RepoStore = {
isCommitable: false,
binary: false,
currentBranch: '',
targetBranch: 'new-branch',
commitMessage: '',
binaryTypes: {
png: false,
......
......@@ -43,6 +43,8 @@ import Cookies from 'js-cookie';
$allGutterToggleIcons.removeClass('fa-angle-double-left').addClass('fa-angle-double-right');
$('aside.right-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
$('.page-with-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
if (gl.lazyLoader) gl.lazyLoader.loadCheck();
}
if (!triggered) {
return Cookies.set("collapsed_gutter", $('.right-sidebar').hasClass('right-sidebar-collapsed'));
......
......@@ -38,7 +38,7 @@ class SidebarMoveIssue {
data: (searchTerm, callback) => {
this.mediator.fetchAutocompleteProjects(searchTerm)
.then(callback)
.catch(() => new Flash('An error occured while fetching projects autocomplete.'));
.catch(() => new Flash('An error occurred while fetching projects autocomplete.'));
},
renderRow: project => `
<li>
......@@ -73,7 +73,7 @@ class SidebarMoveIssue {
this.mediator.moveIssue()
.catch(() => {
Flash('An error occured while moving the issue.');
Flash('An error occurred while moving the issue.');
this.$confirmButton
.enable()
.removeClass('is-loading');
......
......@@ -41,7 +41,7 @@ export default class SidebarMediator {
this.store.setAssigneeData(data);
this.store.setTimeTrackingData(data);
})
.catch(() => new Flash('Error occured when fetching sidebar data'));
.catch(() => new Flash('Error occurred when fetching sidebar data'));
}
fetchAutocompleteProjects(searchTerm) {
......
......@@ -27,7 +27,7 @@ export default {
<button
v-if="showDisabledButton"
type="button"
class="btn btn-success btn-sm"
class="js-disabled-merge-button btn btn-success btn-sm"
disabled="true">
Merge
</button>
......
......@@ -10,27 +10,37 @@ export default {
},
template: `
<div class="mr-widget-body media">
<status-icon status="failed" showDisabledButton />
<status-icon
status="failed"
showDisabledButton />
<div class="media-body space-children">
<span class="bold">
There are merge conflicts<span v-if="!mr.canMerge">.</span>
<span v-if="!mr.canMerge">
Resolve these conflicts or ask someone with write access to this repository to merge it locally
</span>
<span
v-if="mr.shouldBeRebased"
class="bold">
Fast-forward merge is not possible.
To merge this request, first rebase locally.
</span>
<a
v-if="mr.canMerge && mr.conflictResolutionPath"
:href="mr.conflictResolutionPath"
class="btn btn-default btn-xs js-resolve-conflicts-button">
Resolve conflicts
</a>
<a
v-if="mr.canMerge"
class="btn btn-default btn-xs js-merge-locally-button"
data-toggle="modal"
href="#modal_merge_info">
Merge locally
</a>
<template v-else>
<span class="bold">
There are merge conflicts<span v-if="!mr.canMerge">.</span>
<span v-if="!mr.canMerge">
Resolve these conflicts or ask someone with write access to this repository to merge it locally
</span>
</span>
<a
v-if="mr.canMerge && mr.conflictResolutionPath"
:href="mr.conflictResolutionPath"
class="js-resolve-conflicts-button btn btn-default btn-xs">
Resolve conflicts
</a>
<a
v-if="mr.canMerge"
class="js-merge-locally-button btn btn-default btn-xs"
data-toggle="modal"
href="#modal_merge_info">
Merge locally
</a>
</template>
</div>
</div>
`,
......
......@@ -288,14 +288,16 @@ export default {
:mr="mr"
:is-merge-button-disabled="isMergeButtonDisabled" />
<span v-if="mr.ffOnlyEnabled">
<span
v-if="mr.ffOnlyEnabled"
class="js-fast-forward-message">
Fast-forward merge without a merge commit
</span>
<button
v-else
@click="toggleCommitMessageEditor"
:disabled="isMergeButtonDisabled"
class="btn btn-default btn-xs"
class="js-modify-commit-message-button btn btn-default btn-xs"
type="button">
Modify commit message
</button>
......
......@@ -59,6 +59,8 @@ export default class MergeRequestStore {
this.onlyAllowMergeIfPipelineSucceeds = data.only_allow_merge_if_pipeline_succeeds || false;
this.mergeWhenPipelineSucceeds = data.merge_when_pipeline_succeeds || false;
this.mergePath = data.merge_path;
this.ffOnlyEnabled = data.ff_only_enabled;
this.shouldBeRebased = !!data.should_be_rebased;
this.statusPath = data.status_path;
this.emailPatchesPath = data.email_patches_path;
this.plainDiffPath = data.plain_diff_path;
......
......@@ -535,7 +535,6 @@
}
.diff-notes-collapse {
position: relative;
width: 19px;
height: 19px;
padding: 0;
......@@ -543,11 +542,7 @@
z-index: 100;
svg {
position: absolute;
left: 50%;
top: 50%;
margin-left: -5.5px;
margin-top: -5.5px;
vertical-align: text-top;
}
path {
......
......@@ -16,7 +16,7 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :authorize_create_issue!, only: [:new, :create]
# Allow modify issue
before_action :authorize_update_issue!, only: [:edit, :update, :move]
before_action :authorize_update_issue!, only: [:update, :move]
# Allow create a new branch and empty WIP merge request from current issue
before_action :authorize_create_merge_request!, only: [:create_merge_request]
......@@ -65,10 +65,6 @@ class Projects::IssuesController < Projects::ApplicationController
respond_with(@issue)
end
def edit
respond_with(@issue)
end
def show
@noteable = @issue
@note = @project.notes.new(noteable: @issue)
......@@ -128,10 +124,6 @@ class Projects::IssuesController < Projects::ApplicationController
@issue = Issues::UpdateService.new(project, current_user, update_params).execute(issue)
respond_to do |format|
format.html do
recaptcha_check_with_fallback { render :edit }
end
format.json do
render_issue_json
end
......
......@@ -347,6 +347,7 @@ class ProjectsController < Projects::ApplicationController
:tag_list,
:visibility_level,
:template_name,
:merge_method,
project_feature_attributes: %i[
builds_access_level
......
module CustomAttributesFilter
def by_custom_attributes(items)
return items unless params[:custom_attributes].is_a?(Hash)
return items unless Ability.allowed?(current_user, :read_custom_attribute)
association = items.reflect_on_association(:custom_attributes)
attributes_table = association.klass.arel_table
attributable_table = items.model.arel_table
custom_attributes = association.klass.select('true').where(
attributes_table[association.foreign_key]
.eq(attributable_table[association.association_primary_key])
)
# perform a subquery for each attribute to be filtered
params[:custom_attributes].inject(items) do |scope, (key, value)|
scope.where('EXISTS (?)', custom_attributes.where(key: key, value: value))
end
end
end
......@@ -16,6 +16,7 @@
#
class UsersFinder
include CreatedAtFilter
include CustomAttributesFilter
attr_accessor :current_user, :params
......@@ -33,6 +34,7 @@ class UsersFinder
users = by_external_identity(users)
users = by_external(users)
users = by_created_at(users)
users = by_custom_attributes(users)
users = by_non_ldap(users)
users
......
......@@ -10,11 +10,7 @@ module BreadcrumbsHelper
def breadcrumb_title_link
return @breadcrumb_link if @breadcrumb_link
if controller.available_action?(:index)
url_for(action: "index")
else
request.path
end
request.path
end
def breadcrumb_title(title)
......
......@@ -249,16 +249,25 @@ module IssuablesHelper
Gitlab::IssuablesCountForState.new(finder)[state]
end
def close_issuable_url(issuable)
issuable_url(issuable, close_reopen_params(issuable, :close))
def close_issuable_path(issuable)
issuable_path(issuable, close_reopen_params(issuable, :close))
end
def reopen_issuable_url(issuable)
issuable_url(issuable, close_reopen_params(issuable, :reopen))
def reopen_issuable_path(issuable)
issuable_path(issuable, close_reopen_params(issuable, :reopen))
end
def close_reopen_issuable_url(issuable, should_inverse = false)
issuable.closed? ^ should_inverse ? reopen_issuable_url(issuable) : close_issuable_url(issuable)
def close_reopen_issuable_path(issuable, should_inverse = false)
issuable.closed? ^ should_inverse ? reopen_issuable_path(issuable) : close_issuable_path(issuable)
end
def issuable_path(issuable, *options)
case issuable
when Issue
issue_path(issuable, *options)
when MergeRequest
merge_request_path(issuable, *options)
end
end
def issuable_url(issuable, *options)
......
......@@ -23,6 +23,7 @@ class GeoNode < ActiveRecord::Base
validates :encrypted_secret_access_key, presence: true
validates :geo_node_key, presence: true, if: :secondary?
validate :check_not_adding_primary_as_secondary, if: :secondary?
after_initialize :build_dependents
after_save :expire_cache!
......@@ -216,12 +217,12 @@ class GeoNode < ActiveRecord::Base
end
end
def validate(record)
# Prevent locking yourself out
if record.host == Gitlab.config.gitlab.host &&
record.port == Gitlab.config.gitlab.port &&
record.relative_url_root == Gitlab.config.gitlab.relative_url_root && !record.primary
record.errors[:base] << 'Current node must be the primary node or you will be locking yourself out'
# Prevent locking yourself out
def check_not_adding_primary_as_secondary
if host == Gitlab.config.gitlab.host &&
port == Gitlab.config.gitlab.port &&
relative_url_root == Gitlab.config.gitlab.relative_url_root
errors.add(:base, 'Current node must be the primary node or you will be locking yourself out')
end
end
......
......@@ -12,7 +12,6 @@ class License < ActiveRecord::Base
contribution_analytics
elastic_search
export_issues
fast_forward_merge
group_webhooks
issuable_default_templates
issue_board_focus_mode
......@@ -63,7 +62,6 @@ class License < ActiveRecord::Base
cross_project_pipelines
deploy_board
export_issues
fast_forward_merge
file_locks
group_webhooks
issuable_default_templates
......
......@@ -549,6 +549,14 @@ class MergeRequest < ActiveRecord::Base
true
end
def ff_merge_possible?
project.repository.ancestor?(target_branch_sha, diff_head_sha)
end
def should_be_rebased?
project.ff_merge_must_be_possible? && !ff_merge_possible?
end
def can_cancel_merge_when_pipeline_succeeds?(current_user)
can_be_merged_by?(current_user) || self.author == current_user
end
......
......@@ -1035,7 +1035,7 @@ class Project < ActiveRecord::Base
# Forked import is handled asynchronously
return if forked? && !force
if gitlab_shell.add_repository(repository_storage_path, disk_path)
if gitlab_shell.add_repository(repository_storage, disk_path)
repository.after_create
true
else
......@@ -1586,6 +1586,34 @@ class Project < ActiveRecord::Base
Gitlab::GlRepository.gl_repository(self, is_wiki)
end
def merge_method
if self.merge_requests_ff_only_enabled
:ff
elsif self.merge_requests_rebase_enabled
:rebase_merge
else
:merge
end
end
def merge_method=(method)
case method.to_s
when "ff"
self.merge_requests_ff_only_enabled = true
self.merge_requests_rebase_enabled = true
when "rebase_merge"
self.merge_requests_ff_only_enabled = false
self.merge_requests_rebase_enabled = true
when "merge"
self.merge_requests_ff_only_enabled = false
self.merge_requests_rebase_enabled = false
end
end
def ff_merge_must_be_possible?
self.merge_requests_ff_only_enabled || self.merge_requests_rebase_enabled
end
private
def storage
......
......@@ -189,7 +189,7 @@ class ProjectWiki
private
def init_repo(disk_path)
gitlab_shell.add_repository(project.repository_storage_path, disk_path)
gitlab_shell.add_repository(project.repository_storage, disk_path)
end
def commit_details(action, message = nil, title = nil)
......
......@@ -496,13 +496,7 @@ class Repository
def exists?
return false unless full_path
Gitlab::GitalyClient.migrate(:repository_exists) do |enabled|
if enabled
raw_repository.exists?
else
refs_directory_exists?
end
end
raw_repository.exists?
end
cache_method :exists?
......@@ -1143,12 +1137,6 @@ class Repository
blob.data
end
def refs_directory_exists?
circuit_breaker.perform do
File.exist?(File.join(path_to_repo, 'refs'))
end
end
def cache
# TODO: should we use UUIDs here? We could move repositories without clearing this cache
@cache ||= RepositoryCache.new(full_path, @project.id)
......@@ -1200,10 +1188,6 @@ class Repository
Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', Gitlab::GlRepository.gl_repository(project, false))
end
def circuit_breaker
@circuit_breaker ||= Gitlab::Git::Storage::CircuitBreaker.for_storage(project.repository_storage)
end
def find_commits_by_message_by_shelling_out(query, ref, path, limit, offset)
ref ||= root_ref
......
......@@ -133,6 +133,8 @@ class User < ActiveRecord::Base
has_many :assigned_issues, class_name: "Issue", through: :issue_assignees, source: :issue
has_many :assigned_merge_requests, dependent: :nullify, foreign_key: :assignee_id, class_name: "MergeRequest" # rubocop:disable Cop/ActiveRecordDependent
has_many :custom_attributes, class_name: 'UserCustomAttribute'
#
# Validations
#
......
class UserCustomAttribute < ActiveRecord::Base
belongs_to :user
validates :user_id, :key, :value, presence: true
validates :key, uniqueness: { scope: [:user_id] }
end
......@@ -47,4 +47,9 @@ class GlobalPolicy < BasePolicy
rule { ~(anonymous & restricted_public_level) }.policy do
enable :read_users_list
end
rule { admin }.policy do
enable :read_custom_attribute
enable :update_custom_attribute
end
end
......@@ -14,6 +14,7 @@ module MergeRequests
notification_service.merge_mr(merge_request, current_user)
execute_hooks(merge_request, 'merge')
invalidate_cache_counts(merge_request, users: merge_request.assignees)
merge_request.update_project_counter_caches
end
private
......
......@@ -11,7 +11,7 @@ module Tags
begin
new_tag = repository.add_tag(current_user, tag_name, target, message)
rescue Rugged::TagError
rescue Gitlab::Git::Repository::TagExistsError
return error("Tag #{tag_name} already exists")
rescue Gitlab::Git::HooksService::PreReceiveError => ex
return error(ex.message)
......
......@@ -12,10 +12,10 @@ module Users
def execute(validate: true, &block)
yield(@user) if block_given?
assign_attributes(&block)
user_exists = @user.persisted?
assign_attributes(&block)
if @user.save(validate: validate)
notify_success(user_exists)
else
......@@ -31,7 +31,7 @@ module Users
true
end
protected
private
def notify_success(user_exists)
notify_new_user(@user, nil) unless user_exists
......@@ -39,8 +39,6 @@ module Users
success
end
private
def assign_attributes(&block)
if @user.user_synced_attributes_metadata
params.except!(*@user.user_synced_attributes_metadata.read_only_attributes)
......
- confirmation_link = confirmation_url(@resource, confirmation_token: @token)
- if @resource.unconfirmed_email.present?
#content
= email_default_heading(@resource.unconfirmed_email)
%p Click the link below to confirm your email address.
#cta
= link_to 'Confirm your email address', confirmation_url(@resource, confirmation_token: @token)
= link_to confirmation_link, confirmation_link
- else
#content
- if Gitlab.com?
......@@ -12,4 +13,4 @@
= email_default_heading("Welcome, #{@resource.name}!")
%p To get started, click the link below to confirm your account.
#cta
= link_to 'Confirm your account', confirmation_url(@resource, confirmation_token: @token)
= link_to confirmation_link, confirmation_link
......@@ -26,19 +26,19 @@
= link_to search_path, title: 'Search', aria: { label: "Search" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('search')
- if current_user
%li.user-counter
= nav_link(path: 'dashboard#issues', html_options: { class: "user-counter" }) do
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues', aria: { label: "Issues" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= custom_icon('issues')
- issues_count = assigned_issuables_count(:issues)
%span.badge.issues-count{ class: ('hidden' if issues_count.zero?) }
= number_with_delimiter(issues_count)
%li.user-counter
= nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter" }) do
= link_to assigned_mrs_dashboard_path, title: 'Merge requests', class: 'dashboard-shortcuts-merge_requests', aria: { label: "Merge requests" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= custom_icon('mr_bold')
- merge_requests_count = assigned_issuables_count(:merge_requests)
%span.badge.merge-requests-count{ class: ('hidden' if merge_requests_count.zero?) }
= number_with_delimiter(merge_requests_count)
%li.user-counter
= nav_link(controller: 'dashboard/todos', html_options: { class: "user-counter" }) do
= link_to dashboard_todos_path, title: 'Todos', aria: { label: "Todos" }, class: 'shortcuts-todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= custom_icon('todo_done')
%span.badge.todos-count{ class: ('hidden' if todos_pending_count.zero?) }
......
......@@ -16,5 +16,5 @@
= breadcrumb_list_item link_to(extra[:text], extra[:link])
= render "layouts/nav/breadcrumbs/collapsed_dropdown", location: :after
%li
%h2.breadcrumbs-sub-title= @breadcrumb_title
%h2.breadcrumbs-sub-title= link_to @breadcrumb_title, breadcrumb_title_link
= yield :header_content
- form = local_assigns.fetch(:form)
- project = local_assigns.fetch(:project)
.radio
= label_tag :project_merge_method_ff do
= form.radio_button :merge_method, :ff, class: "js-merge-method-radio"
%strong Fast-forward merge
%br
%span.descr
No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.
%br
%span.descr
When fast-forward merge is not possible, the user must first rebase locally.
- form = local_assigns.fetch(:form)
.radio
= label_tag :project_merge_method_rebase_merge do
= form.radio_button :merge_method, :rebase_merge, class: "js-merge-method-radio"
%strong Merge commit with semi-linear history
%br
%span.descr
A merge commit is created for every merge, but merging is only allowed if fast-forward merge is possible.
This way you could make sure that if this merge request would build, after merging to target branch it would also build.
%br
%span.descr
When fast-forward merge is not possible, the user must first rebase locally.
- form = local_assigns.fetch(:form)
= render 'projects/ee/merge_request_settings', form: form, project: @project
.form-group
= label_tag :merge_method_merge, class: 'label-light' do
Merge method
.radio
= label_tag :project_merge_method_merge do
= form.radio_button :merge_method, :merge, class: "js-merge-method-radio"
%strong Merge commit
%br
%span.descr
A merge commit is created for every merge, and merging is allowed as long as there are no conflicts.
= render 'merge_request_rebase_settings', form: form
= render 'merge_request_fast_forward_settings', project: @project, form: form
= render 'projects/merge_request_merge_settings', form: form
......@@ -95,7 +95,7 @@
= render 'shared/promotions/promote_mr_features'
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings-form" }, authenticity_token: true do |f|
= render 'merge_request_settings', form: f
= render 'projects/ee/merge_request_settings', form: f
= f.submit 'Save changes', class: "btn btn-save"
= render 'projects/ee/service_desk_settings'
......
- page_title "Edit", "#{@issue.title} (#{@issue.to_reference})", "Issues"
%h3.page-title
Edit Issue ##{@issue.iid}
%hr
= render "form"
- access = note_max_access_for_user(note)
- if note.has_special_role?(Note::SpecialRole::FIRST_TIME_CONTRIBUTOR)
%span.note-role.note-role-special.has-tooltip{ title: _("This is the author's first Merge Request to this project. Handle with care.") }
%span.note-role.note-role-special.has-tooltip{ title: _("This is the author's first Merge Request to this project.") }
= issuable_first_contribution_icon
- if access.nonzero?
%span.note-role.note-role-access= Gitlab::Access.human_access(access)
......
.tree-ref-container
.tree-ref-holder
= render 'shared/ref_switcher', destination: 'tree', path: @path
- if show_new_repo?
.tree-ref-target-holder.js-tree-ref-target-holder
= icon('long-arrow-right', title: 'to target branch')
= render 'shared/target_switcher', destination: 'tree', path: @path
- unless show_new_repo?
= render 'projects/tree/old_tree_header'
......
- dropdown_toggle_text = @ref || @project.default_branch
= form_tag nil, method: :get, class: "project-refs-form project-refs-target-form" do
= hidden_field_tag :destination, destination
- if defined?(path)
= hidden_field_tag :path, path
- @options && @options.each do |key, value|
= hidden_field_tag key, value, id: nil
.dropdown
= dropdown_toggle dropdown_toggle_text, { toggle: "dropdown", selected: dropdown_toggle_text, ref: @ref, refs_url: refs_project_path(@project, find: ['branches']), field_name: 'ref', input_field_name: 'new-branch', submit_form_on_click: true, visit: false }, { toggle_class: "js-project-refs-dropdown" }
.dropdown-menu.dropdown-menu-selectable.git-revision-dropdown{ class: ("dropdown-menu-align-right" if local_assigns[:align_right]) }
= dropdown_title _("Create a new branch")
= dropdown_input _("Create a new branch")
= dropdown_title _("Select existing branch"), options: {close: false}
= dropdown_filter _("Search branches and tags")
= dropdown_content
= dropdown_loading
......@@ -34,7 +34,7 @@
- case purchase_link.action
- when 'downgrade'
= plan_purchase_link(href, s_("Billinglans|Downgrade"))
= plan_purchase_link(href, s_("BillingPlans|Downgrade"))
- when 'current_plan'
= plan_purchase_link(href, s_("BillingPlans|Current plan"))
- when 'upgrade'
......
......@@ -3,9 +3,9 @@
- button_method = issuable_close_reopen_button_method(issuable)
- if can_update && is_current_user
= link_to "Close #{display_issuable_type}", close_issuable_url(issuable), method: button_method,
= link_to "Close #{display_issuable_type}", close_issuable_path(issuable), method: button_method,
class: "hidden-xs hidden-sm btn btn-grouped btn-close js-btn-issue-action #{issuable_button_visibility(issuable, true)}", title: "Close #{display_issuable_type}"
= link_to "Reopen #{display_issuable_type}", reopen_issuable_url(issuable), method: button_method,
= link_to "Reopen #{display_issuable_type}", reopen_issuable_path(issuable), method: button_method,
class: "hidden-xs hidden-sm btn btn-grouped btn-reopen js-btn-issue-action #{issuable_button_visibility(issuable, false)}", title: "Reopen #{display_issuable_type}"
- elsif can_update && !is_current_user
= render 'shared/issuable/close_reopen_report_toggle', issuable: issuable
......
......@@ -7,7 +7,7 @@
- button_method = issuable_close_reopen_button_method(issuable)
.pull-left.btn-group.prepend-left-10.issuable-close-dropdown.droplab-dropdown.js-issuable-close-dropdown
= link_to "#{display_button_action} #{display_issuable_type}", close_reopen_issuable_url(issuable),
= link_to "#{display_button_action} #{display_issuable_type}", close_reopen_issuable_path(issuable),
method: button_method, class: "#{button_class} btn-#{button_action}", title: "#{display_button_action} #{display_issuable_type}"
= button_tag type: 'button', class: "#{toggle_class} btn-#{button_action}-color",
......@@ -16,7 +16,7 @@
%ul#issuable-close-menu.js-issuable-close-menu.dropdown-menu{ class: button_responsive_class, data: { dropdown: true } }
%li.close-item{ class: "#{issuable_button_visibility(issuable, true) || 'droplab-item-selected'}",
data: { text: "Close #{display_issuable_type}", url: close_issuable_url(issuable),
data: { text: "Close #{display_issuable_type}", url: close_issuable_path(issuable),
button_class: "#{button_class} btn-close", toggle_class: "#{toggle_class} btn-close-color", method: button_method } }
%button.btn.btn-transparent
= icon('check', class: 'icon')
......@@ -26,7 +26,7 @@
= display_issuable_type
%li.reopen-item{ class: "#{issuable_button_visibility(issuable, false) || 'droplab-item-selected'}",
data: { text: "Reopen #{display_issuable_type}", url: reopen_issuable_url(issuable),
data: { text: "Reopen #{display_issuable_type}", url: reopen_issuable_path(issuable),
button_class: "#{button_class} btn-reopen", toggle_class: "#{toggle_class} btn-reopen-color", method: button_method } }
%button.btn.btn-transparent
= icon('check', class: 'icon')
......
......@@ -16,7 +16,7 @@ class StuckImportJobsWorker
private
def mark_projects_without_jid_as_failed!
started_projects_without_jid.each do |project|
enqueued_projects_without_jid.each do |project|
project.mark_import_as_failed(error_message)
end.count
end
......@@ -24,7 +24,7 @@ class StuckImportJobsWorker
def mark_projects_with_jid_as_failed!
completed_jids_count = 0
started_projects_with_jid.find_in_batches(batch_size: 500) do |group|
enqueued_projects_with_jid.find_in_batches(batch_size: 500) do |group|
jids = group.map(&:import_jid)
# Find the jobs that aren't currently running or that exceeded the threshold.
......@@ -43,16 +43,16 @@ class StuckImportJobsWorker
completed_jids_count
end
def started_projects
Project.with_import_status(:started)
def enqueued_projects
Project.with_import_status(:scheduled, :started)
end
def started_projects_with_jid
started_projects.where.not(import_jid: nil)
def enqueued_projects_with_jid
enqueued_projects.where.not(import_jid: nil)
end
def started_projects_without_jid
started_projects.where(import_jid: nil)
def enqueued_projects_without_jid
enqueued_projects.where(import_jid: nil)
end
def error_message
......
---
title: Adds hoverstates for collapsed Issue/Merge Request sidebar for Time tracking Icon
merge_request:
author:
---
title: Fix a Geo node validation, preventing admins from locking themselves out
merge_request: 3040
author:
type: fixed
---
title: Find stuck scheduled import jobs and also mark them as failed.
merge_request: 3055
author:
type: fixed
---
title: Fix EE delta size check handling with annotated tags
merge_request:
author:
type: fixed
---
title: "Fix v3 api project_hooks POST and PUT operations for build_events"
merge_request: 12673
author: Richard Clamp
---
title: "reset text-align to initial to let elements with dir="auto" align texts to right in RTL languages ( default is left )"
merge_request: 12892
author: goshhob
---
title: Confirmation email shows link as text instead of human readable text
merge_request: 14243
author: bitsapien
type: changed
......@@ -2,5 +2,5 @@
title: Allow to use same periods for different housekeeping tasks (effectively
skipping the lesser task)
merge_request: 13711
author: @cernvcs
author: cernvcs
type: added
---
title: Handle unsubscribe from email notifications via replying to reply+%{key}+unsubscribe@ address
merge_request: 6597
author:
---
title: Refactor Timelogs structure to use foreign keys.
merge_request: 8769
author:
---
title: "Correction to documention for manual steps on the Jobs API"
merge_request: 11411
author: Zac Sturgess
\ No newline at end of file
---
title: "Fix API to serve binary diffs that are treated as text."
merge_request: 14038
---
title: Remove the ability to visit the issue edit form directly
merge_request: 14523
author:
type: removed
---
title: Add GitLab-Pages version to Admin Dashboard
merge_request: 14040
author: @travismiller
author: travismiller
type: added
---
title: Add active states to nav bar counters
merge_request:
author:
type: changed
---
title: Fix 500 error on merged merge requests when GitLab is restored from a backup
merge_request:
author:
type: fixed
---
title: Fix notes type created from import. This should fix some missing notes issues
from imported projects
merge_request: 14524
author:
type: fixed
---
title: Adjust MRs being stuck on "process of being merged" for more than 2 hours
merge_request:
author:
type: fixed
---
title: Fixes data parameter not being sent in ajax request for jobs log
merge_request:
author:
type: fixed
---
title: Add index for merge_requests.merge_commit_sha
merge_request:
author:
type: other
---
title: Added mock deployment and monitoring service with environments fixtures
merge_request:
author:
---
title: Fixed issue/merge request breadcrumb titles not having links
merge_request:
author:
type: fixed
---
title: Fix CSRF validation issue when closing/opening merge requests from the UI
merge_request: 14555
author:
type: fixed
---
title: Fixed commenting on side-by-side commit diff
merge_request:
author:
type: fixed
---
title: Make sure API responds with 401 when invalid authentication info is provided
merge_request:
author:
type: fixed
---
title: Clarify artifact download via the API only accepts branch or tag name for ref
merge_request:
author:
type: other
---
title: Change recommended MySQL version to 5.6
merge_request:
author:
type: other
---
title: Support custom attributes on users
merge_request: 13038
author: Markus Koller
---
title: Fix merge request counter updates after merge
merge_request:
author:
type: fixed
---
title: Detect when changelog entries are invalid
merge_request:
author:
type: other
---
title: Added ability to put emojis into repository name
merge_request: 7420
author: Vincent Composieux
---
title: Fix profile image orientation based on EXIF data gvieira37
merge_request: 14461
author: gvieira37
type: fixed
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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