Commit 9763cc76 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'ce-to-ee-2018-05-02' into 'master'

CE upstream - 2018-05-02 18:27 UTC

See merge request gitlab-org/gitlab-ee!5551
parents 20e12599 bc5cc956
export default {
name: 'time-tracking-no-tracking-pane',
template: `
<div class="time-tracking-no-tracking-pane">
<span class="no-value">
{{ __('No estimate or time spent') }}
</span>
</div>
`,
};
<script>
export default {
name: 'TimeTrackingNoTrackingPane',
};
</script>
<template>
<div class="time-tracking-no-tracking-pane">
<span class="no-value">
{{ __('No estimate or time spent') }}
</span>
</div>
</template>
<script>
import $ from 'jquery'; import $ from 'jquery';
import _ from 'underscore'; import _ from 'underscore';
...@@ -10,14 +11,17 @@ import Mediator from '../../sidebar_mediator'; ...@@ -10,14 +11,17 @@ import Mediator from '../../sidebar_mediator';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
export default { export default {
components: {
IssuableTimeTracker,
},
data() { data() {
return { return {
mediator: new Mediator(), mediator: new Mediator(),
store: new Store(), store: new Store(),
}; };
}, },
components: { mounted() {
IssuableTimeTracker, this.listenForQuickActions();
}, },
methods: { methods: {
listenForQuickActions() { listenForQuickActions() {
...@@ -41,18 +45,17 @@ export default { ...@@ -41,18 +45,17 @@ export default {
} }
}, },
}, },
mounted() {
this.listenForQuickActions();
},
template: `
<div class="block">
<issuable-time-tracker
:time_estimate="store.timeEstimate"
:time_spent="store.totalTimeSpent"
:human_time_estimate="store.humanTimeEstimate"
:human_time_spent="store.humanTotalTimeSpent"
:rootPath="store.rootPath"
/>
</div>
`,
}; };
</script>
<template>
<div class="block">
<issuable-time-tracker
:time_estimate="store.timeEstimate"
:time_spent="store.totalTimeSpent"
:human_time_estimate="store.humanTimeEstimate"
:human_time_spent="store.humanTotalTimeSpent"
:root-path="store.rootPath"
/>
</div>
</template>
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import TimeTrackingHelpState from './help_state.vue'; import TimeTrackingHelpState from './help_state.vue';
import TimeTrackingCollapsedState from './collapsed_state.vue'; import TimeTrackingCollapsedState from './collapsed_state.vue';
import timeTrackingSpentOnlyPane from './spent_only_pane'; import timeTrackingSpentOnlyPane from './spent_only_pane';
import timeTrackingNoTrackingPane from './no_tracking_pane'; import TimeTrackingNoTrackingPane from './no_tracking_pane.vue';
import TimeTrackingEstimateOnlyPane from './estimate_only_pane.vue'; import TimeTrackingEstimateOnlyPane from './estimate_only_pane.vue';
import TimeTrackingComparisonPane from './comparison_pane.vue'; import TimeTrackingComparisonPane from './comparison_pane.vue';
...@@ -14,7 +14,7 @@ export default { ...@@ -14,7 +14,7 @@ export default {
TimeTrackingCollapsedState, TimeTrackingCollapsedState,
TimeTrackingEstimateOnlyPane, TimeTrackingEstimateOnlyPane,
'time-tracking-spent-only-pane': timeTrackingSpentOnlyPane, 'time-tracking-spent-only-pane': timeTrackingSpentOnlyPane,
'time-tracking-no-tracking-pane': timeTrackingNoTrackingPane, TimeTrackingNoTrackingPane,
TimeTrackingComparisonPane, TimeTrackingComparisonPane,
TimeTrackingHelpState, TimeTrackingHelpState,
}, },
......
import $ from 'jquery'; import $ from 'jquery';
import Vue from 'vue'; import Vue from 'vue';
import SidebarTimeTracking from './components/time_tracking/sidebar_time_tracking'; import SidebarTimeTracking from './components/time_tracking/sidebar_time_tracking.vue';
import SidebarAssignees from './components/assignees/sidebar_assignees.vue'; import SidebarAssignees from './components/assignees/sidebar_assignees.vue';
import ConfidentialIssueSidebar from './components/confidential/confidential_issue_sidebar.vue'; import ConfidentialIssueSidebar from './components/confidential/confidential_issue_sidebar.vue';
import SidebarMoveIssue from './lib/sidebar_move_issue'; import SidebarMoveIssue from './lib/sidebar_move_issue';
......
<script>
import $ from 'jquery'; import $ from 'jquery';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
import tooltip from '../../../vue_shared/directives/tooltip'; import tooltip from '../../../vue_shared/directives/tooltip';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
export default { export default {
name: 'MRWidgetWIP', name: 'WorkInProgress',
props: { components: {
mr: { type: Object, required: true }, statusIcon,
service: { type: Object, required: true },
}, },
directives: { directives: {
tooltip, tooltip,
}, },
props: {
mr: { type: Object, required: true },
service: { type: Object, required: true },
},
data() { data() {
return { return {
isMakingRequest: false, isMakingRequest: false,
}; };
}, },
components: {
statusIcon,
},
methods: { methods: {
removeWIP() { removeWIP() {
this.isMakingRequest = true; this.isMakingRequest = true;
...@@ -36,32 +37,40 @@ export default { ...@@ -36,32 +37,40 @@ export default {
}); });
}, },
}, },
template: `
<div class="mr-widget-body media">
<status-icon status="warning" :show-disabled-button="Boolean(mr.removeWIPPath)" />
<div class="media-body space-children">
<span class="bold">
This is a Work in Progress
<i
v-tooltip
class="fa fa-question-circle"
title="When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged"
aria-label="When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged">
</i>
</span>
<button
v-if="mr.removeWIPPath"
@click="removeWIP"
:disabled="isMakingRequest"
type="button"
class="btn btn-default btn-xs js-remove-wip">
<i
v-if="isMakingRequest"
class="fa fa-spinner fa-spin"
aria-hidden="true" />
Resolve WIP status
</button>
</div>
</div>
`,
}; };
</script>
<template>
<div class="mr-widget-body media">
<status-icon
status="warning"
:show-disabled-button="Boolean(mr.removeWIPPath)"
/>
<div class="media-body space-children">
<span class="bold">
This is a Work in Progress
<i
v-tooltip
class="fa fa-question-circle"
title="When this merge request is ready,
remove the WIP: prefix from the title to allow it to be merged"
aria-label="When this merge request is ready,
remove the WIP: prefix from the title to allow it to be merged">
</i>
</span>
<button
v-if="mr.removeWIPPath"
@click="removeWIP"
:disabled="isMakingRequest"
type="button"
class="btn btn-default btn-xs js-remove-wip">
<i
v-if="isMakingRequest"
class="fa fa-spinner fa-spin"
aria-hidden="true">
</i>
Resolve WIP status
</button>
</div>
</div>
</template>
...@@ -21,7 +21,7 @@ export { default as MergedState } from './components/states/mr_widget_merged.vue ...@@ -21,7 +21,7 @@ export { default as MergedState } from './components/states/mr_widget_merged.vue
export { default as FailedToMerge } from './components/states/mr_widget_failed_to_merge.vue'; export { default as FailedToMerge } from './components/states/mr_widget_failed_to_merge.vue';
export { default as ClosedState } from './components/states/mr_widget_closed.vue'; export { default as ClosedState } from './components/states/mr_widget_closed.vue';
export { default as MergingState } from './components/states/mr_widget_merging.vue'; export { default as MergingState } from './components/states/mr_widget_merging.vue';
export { default as WipState } from './components/states/mr_widget_wip'; export { default as WorkInProgressState } from './components/states/work_in_progress.vue';
export { default as ArchivedState } from './components/states/mr_widget_archived.vue'; export { default as ArchivedState } from './components/states/mr_widget_archived.vue';
export { default as ConflictsState } from './components/states/mr_widget_conflicts.vue'; export { default as ConflictsState } from './components/states/mr_widget_conflicts.vue';
export { default as NothingToMergeState } from './components/states/nothing_to_merge.vue'; export { default as NothingToMergeState } from './components/states/nothing_to_merge.vue';
......
...@@ -12,7 +12,7 @@ import { ...@@ -12,7 +12,7 @@ import {
ClosedState, ClosedState,
MergingState, MergingState,
RebaseState, RebaseState,
WipState, WorkInProgressState,
ArchivedState, ArchivedState,
ConflictsState, ConflictsState,
NothingToMergeState, NothingToMergeState,
...@@ -221,7 +221,7 @@ export default { ...@@ -221,7 +221,7 @@ export default {
'mr-widget-closed': ClosedState, 'mr-widget-closed': ClosedState,
'mr-widget-merging': MergingState, 'mr-widget-merging': MergingState,
'mr-widget-failed-to-merge': FailedToMerge, 'mr-widget-failed-to-merge': FailedToMerge,
'mr-widget-wip': WipState, 'mr-widget-wip': WorkInProgressState,
'mr-widget-archived': ArchivedState, 'mr-widget-archived': ArchivedState,
'mr-widget-conflicts': ConflictsState, 'mr-widget-conflicts': ConflictsState,
'mr-widget-nothing-to-merge': NothingToMergeState, 'mr-widget-nothing-to-merge': NothingToMergeState,
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
@import 'framework/tw_bootstrap_variables'; @import 'framework/tw_bootstrap_variables';
@import 'framework/tw_bootstrap'; @import 'framework/tw_bootstrap';
@import 'framework/layout'; @import 'framework/layout';
@import 'framework/animations'; @import 'framework/animations';
@import 'framework/vue_transitions'; @import 'framework/vue_transitions';
@import 'framework/avatar'; @import 'framework/avatar';
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
} }
&.middle-block { &.middle-block {
margin-top: 0; margin-top: $gl-padding-24;
margin-bottom: 0; margin-bottom: 0;
} }
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
} }
&.footer-block { &.footer-block {
margin-top: 0; margin-top: $gl-padding-24;
border-bottom: 0; border-bottom: 0;
margin-bottom: -$gl-padding; margin-bottom: -$gl-padding;
} }
......
...@@ -107,6 +107,16 @@ ...@@ -107,6 +107,16 @@
padding-top: 10px; padding-top: 10px;
} }
.referenced-commands {
background: $blue-50;
padding: $gl-padding-8 $gl-padding;
border-radius: $border-radius-default;
p {
margin: 0;
}
}
.md-preview-holder { .md-preview-holder {
min-height: 167px; min-height: 167px;
padding: 10px 0; padding: 10px 0;
......
...@@ -213,6 +213,7 @@ $tooltip-font-size: 12px; ...@@ -213,6 +213,7 @@ $tooltip-font-size: 12px;
/* /*
* Padding * Padding
*/ */
$gl-padding-24: 24px;
$gl-padding: 16px; $gl-padding: 16px;
$gl-padding-8: 8px; $gl-padding-8: 8px;
$gl-padding-4: 4px; $gl-padding-4: 4px;
......
...@@ -77,21 +77,30 @@ module MergeRequests ...@@ -77,21 +77,30 @@ module MergeRequests
end end
def commit def commit
message = params[:commit_message] || merge_request.merge_commit_message
log_info("Git merge started on JID #{merge_jid}") log_info("Git merge started on JID #{merge_jid}")
commit_id = repository.merge(current_user, source, merge_request, message) commit_id = try_merge
log_info("Git merge finished on JID #{merge_jid} commit #{commit_id}")
if commit_id
log_info("Git merge finished on JID #{merge_jid} commit #{commit_id}")
else
raise MergeError, 'Conflicts detected during merge'
end
raise MergeError, 'Conflicts detected during merge' unless commit_id merge_request.update!(merge_commit_sha: commit_id)
end
def try_merge
message = params[:commit_message] || merge_request.merge_commit_message
merge_request.update(merge_commit_sha: commit_id) repository.merge(current_user, source, merge_request, message)
rescue Gitlab::Git::HooksService::PreReceiveError => e rescue Gitlab::Git::HooksService::PreReceiveError => e
raise MergeError, e.message handle_merge_error(log_message: e.message)
rescue StandardError => e raise MergeError, 'Something went wrong during merge pre-receive hook'
raise MergeError, "Something went wrong during merge: #{e.message}" rescue => e
handle_merge_error(log_message: e.message)
raise MergeError, 'Something went wrong during merge'
ensure ensure
merge_request.update(in_progress_merge_commit_sha: nil) merge_request.update!(in_progress_merge_commit_sha: nil)
end end
def after_merge def after_merge
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
.panel .panel
.panel-heading.alert.alert-danger .panel-heading.alert.alert-danger
Last repository check Last repository check
= "(#{time_ago_in_words(@project.last_repository_check_at)} ago)" = "(#{time_ago_with_tooltip(@project.last_repository_check_at)})"
failed. See failed. See
= link_to 'repocheck.log', admin_logs_path = link_to 'repocheck.log', admin_logs_path
for error messages. for error messages.
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
= tag = tag
%td %td
- if runner.contacted_at - if runner.contacted_at
#{time_ago_in_words(runner.contacted_at)} ago = time_ago_with_tooltip runner.contacted_at
- else - else
Never Never
%td.admin-runner-btn-group-cell %td.admin-runner-btn-group-cell
......
...@@ -108,4 +108,4 @@ ...@@ -108,4 +108,4 @@
%td.timestamp %td.timestamp
- if build.finished_at - if build.finished_at
%span #{time_ago_in_words build.finished_at} ago %span= time_ago_with_tooltip build.finished_at
...@@ -20,5 +20,4 @@ ...@@ -20,5 +20,4 @@
%td %td
= service.description = service.description
%td.light %td.light
= time_ago_in_words service.updated_at = time_ago_with_tooltip service.updated_at
ago
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
= email_default_heading("Hello, #{@resource.name}!") = email_default_heading("Hello, #{@resource.name}!")
%p %p
Your GitLab account has been locked due to an excessive amount of unsuccessful Your GitLab account has been locked due to an excessive amount of unsuccessful
sign in attempts. Your account will automatically unlock in #{time_ago_in_words(Devise.unlock_in.from_now)} sign in attempts. Your account will automatically unlock in #{distance_of_time_in_words(Devise.unlock_in)}
or you may click the link below to unlock now. or you may click the link below to unlock now.
#cta #cta
= link_to('Unlock account', unlock_url(@resource, unlock_token: @token)) = link_to('Unlock account', unlock_url(@resource, unlock_token: @token))
Hello, <%= @resource.name %>! Hello, <%= @resource.name %>!
Your GitLab account has been locked due to an excessive amount of unsuccessful Your GitLab account has been locked due to an excessive amount of unsuccessful
sign in attempts. Your account will automatically unlock in <%= time_ago_in_words(Devise.unlock_in.from_now) %> sign in attempts. Your account will automatically unlock in <%= distance_of_time_in_words(Devise.unlock_in) %>
or you may click the link below to unlock now. or you may click the link below to unlock now.
<%= unlock_url(@resource, unlock_token: @token) %> <%= unlock_url(@resource, unlock_token: @token) %>
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
- elsif @build.has_expiring_artifacts? - elsif @build.has_expiring_artifacts?
%p.build-detail-row %p.build-detail-row
The artifacts will be removed in The artifacts will be removed in
%span= time_ago_in_words @build.artifacts_expire_at %span= time_ago_with_tooltip @build.artifacts_expire_at
- if @build.artifacts? - if @build.artifacts?
.btn-group.btn-group-justified{ role: :group } .btn-group.btn-group-justified{ role: :group }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
\- \-
%td %td
- if tag.created_at - if tag.created_at
= time_ago_in_words(tag.created_at) = time_ago_with_tooltip tag.created_at
- else - else
.light .light
\- \-
......
...@@ -62,6 +62,6 @@ ...@@ -62,6 +62,6 @@
%td Last contact %td Last contact
%td %td
- if @runner.contacted_at - if @runner.contacted_at
#{time_ago_in_words(@runner.contacted_at)} ago = time_ago_with_tooltip @runner.contacted_at
- else - else
Never Never
...@@ -27,5 +27,4 @@ ...@@ -27,5 +27,4 @@
= service.description = service.description
%td.light %td.light
- if service.updated_at.present? - if service.updated_at.present?
= time_ago_in_words service.updated_at = time_ago_with_tooltip service.updated_at
ago
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
%td %td
- if trigger.last_used - if trigger.last_used
#{time_ago_in_words(trigger.last_used)} ago = time_ago_with_tooltip trigger.last_used
- else - else
Never Never
......
...@@ -35,5 +35,4 @@ ...@@ -35,5 +35,4 @@
%span.light %span.light
#{t('sherlock.finished_at')}: #{t('sherlock.finished_at')}:
%strong %strong
= time_ago_in_words(@transaction.finished_at) = time_ago_with_tooltip @transaction.finished_at
= t('sherlock.ago')
...@@ -35,8 +35,7 @@ ...@@ -35,8 +35,7 @@
= t('sherlock.seconds') = t('sherlock.seconds')
%td= trans.queries.length %td= trans.queries.length
%td %td
= time_ago_in_words(trans.finished_at) = time_ago_with_tooltip trans.finished_at
= t('sherlock.ago')
%td %td
= link_to(sherlock_transaction_path(trans), class: 'btn btn-xs') do = link_to(sherlock_transaction_path(trans), class: 'btn btn-xs') do
= t('sherlock.view') = t('sherlock.view')
---
title: Replace time_ago_in_words with JS-based one
merge_request: 18607
author: Takuya Noguchi
type: performance
---
title: Improve quick actions summary preview
merge_request: 18659
author: George Tsiolis
type: changed
---
title: Increase new issue metadata form margin
merge_request: 18630
author: George Tsiolis
type: fixed
---
title: Display only generic message on merge error to avoid exposing any potentially
sensitive or user unfriendly backend messages.
merge_request:
author:
type: fixed
---
title: Move WorkInProgress vue component
merge_request: 17536
author: George Tsiolis
type: performance
---
title: Move TimeTrackingNoTrackingPane vue component
merge_request: 18676
author: George Tsiolis
type: performance
---
title: Move SidebarTimeTracking vue component
merge_request: 18677
author: George Tsiolis
type: performance
---
title: Finish NamespaceService migration to Gitaly
merge_request:
author:
type: performance
require 'spec_helper' require 'spec_helper'
describe Projects::UpdateRepositoryStorageService do describe Projects::UpdateRepositoryStorageService do
include StubConfiguration include Gitlab::ShellAdapter
subject { described_class.new(project) } subject { described_class.new(project) }
...@@ -9,41 +9,23 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -9,41 +9,23 @@ describe Projects::UpdateRepositoryStorageService do
let(:time) { Time.now } let(:time) { Time.now }
before do before do
FileUtils.mkdir('tmp/tests/storage_a')
FileUtils.mkdir('tmp/tests/storage_b')
storages = {
'a' => { 'path' => 'tmp/tests/storage_a' },
'b' => { 'path' => 'tmp/tests/storage_b' }
}
stub_storage_settings(storages)
allow(Time).to receive(:now).and_return(time) allow(Time).to receive(:now).and_return(time)
# This will force the creation of the repository and bypass Gitaly
allow_any_instance_of(Gitlab::Git::Repository).to receive(:exists?).and_return(false)
end
after do
FileUtils.rm_rf('tmp/tests/storage_a')
FileUtils.rm_rf('tmp/tests/storage_b')
end end
context 'without wiki', :disable_gitaly do context 'without wiki' do
let(:project) { create(:project, :repository, repository_storage: 'a', repository_read_only: true, wiki_enabled: false) } let(:project) { create(:project, :repository, repository_read_only: true, wiki_enabled: false) }
context 'when the move succeeds' do context 'when the move succeeds' do
it 'moves the repository to the new storage and unmarks the repository as read only' do it 'moves the repository to the new storage and unmarks the repository as read only' do
old_path = project.repository.path_to_repo
expect_any_instance_of(Gitlab::Git::Repository).to receive(:fetch_repository_as_mirror) expect_any_instance_of(Gitlab::Git::Repository).to receive(:fetch_repository_as_mirror)
.with(project.repository.raw).and_return(true) .with(project.repository.raw).and_return(true)
expect(GitlabShellWorker).to receive(:perform_async)
.with(:mv_repository, 'a', project.disk_path,
"#{project.disk_path}+#{project.id}+moved+#{time.to_i}")
subject.execute('b')
subject.execute('test_second_storage')
expect(project).not_to be_repository_read_only expect(project).not_to be_repository_read_only
expect(project.repository_storage).to eq('b') expect(project.repository_storage).to eq('test_second_storage')
expect(gitlab_shell.exists?('default', old_path)).to be(false)
end end
end end
...@@ -53,56 +35,53 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -53,56 +35,53 @@ describe Projects::UpdateRepositoryStorageService do
.with(project.repository.raw).and_return(false) .with(project.repository.raw).and_return(false)
expect(GitlabShellWorker).not_to receive(:perform_async) expect(GitlabShellWorker).not_to receive(:perform_async)
subject.execute('b') subject.execute('test_second_storage')
expect(project).not_to be_repository_read_only expect(project).not_to be_repository_read_only
expect(project.repository_storage).to eq('a') expect(project.repository_storage).to eq('default')
end end
end end
end end
context 'with wiki', :disable_gitaly do context 'with wiki', :disable_gitaly do
let(:project) { create(:project, :repository, repository_storage: 'a', repository_read_only: true, wiki_enabled: true) } let(:project) { create(:project, :repository, repository_read_only: true, wiki_enabled: true) }
let(:repository_double) { double(:repository) } let(:repository_double) { double(:repository) }
let(:wiki_repository_double) { double(:repository) } let(:wiki_repository_double) { double(:repository) }
before do before do
allow_any_instance_of(Gitlab::Git::Repository).to receive(:exists?).and_return(false)
project.create_wiki project.create_wiki
allow_any_instance_of(Gitlab::Git::Repository).to receive(:exists?).and_return(true)
# Default stub for non-specified params # Default stub for non-specified params
allow(Gitlab::Git::Repository).to receive(:new).and_call_original allow(Gitlab::Git::Repository).to receive(:new).and_call_original
relative_path = project.repository.raw.relative_path relative_path = project.repository.raw.relative_path
allow(Gitlab::Git::Repository).to receive(:new) allow(Gitlab::Git::Repository).to receive(:new)
.with('b', relative_path, "project-#{project.id}") .with('test_second_storage', relative_path, "project-#{project.id}")
.and_return(repository_double) .and_return(repository_double)
wiki_relative_path = project.wiki.repository.raw.relative_path wiki_relative_path = project.wiki.repository.raw.relative_path
allow(Gitlab::Git::Repository).to receive(:new) allow(Gitlab::Git::Repository).to receive(:new)
.with('b', wiki_relative_path, "wiki-#{project.id}") .with('test_second_storage', wiki_relative_path, "wiki-#{project.id}")
.and_return(wiki_repository_double) .and_return(wiki_repository_double)
end end
context 'when the move succeeds' do context 'when the move succeeds' do
it 'moves the repository and its wiki to the new storage and unmarks the repository as read only' do it 'moves the repository and its wiki to the new storage and unmarks the repository as read only' do
old_path = project.repository.path_to_repo
old_wiki_path = project.wiki.full_path
expect(repository_double).to receive(:fetch_repository_as_mirror) expect(repository_double).to receive(:fetch_repository_as_mirror)
.with(project.repository.raw).and_return(true) .with(project.repository.raw).and_return(true)
expect(GitlabShellWorker).to receive(:perform_async)
.with(:mv_repository, "a", project.disk_path,
"#{project.disk_path}+#{project.id}+moved+#{time.to_i}")
expect(wiki_repository_double).to receive(:fetch_repository_as_mirror) expect(wiki_repository_double).to receive(:fetch_repository_as_mirror)
.with(project.wiki.repository.raw).and_return(true) .with(project.wiki.repository.raw).and_return(true)
expect(GitlabShellWorker).to receive(:perform_async)
.with(:mv_repository, "a", project.wiki.disk_path,
"#{project.disk_path}+#{project.id}+moved+#{time.to_i}.wiki")
subject.execute('b') subject.execute('test_second_storage')
expect(project).not_to be_repository_read_only expect(project).not_to be_repository_read_only
expect(project.repository_storage).to eq('b') expect(project.repository_storage).to eq('test_second_storage')
expect(gitlab_shell.exists?('default', old_path)).to be(false)
expect(gitlab_shell.exists?('default', old_wiki_path)).to be(false)
end end
end end
...@@ -114,10 +93,10 @@ describe Projects::UpdateRepositoryStorageService do ...@@ -114,10 +93,10 @@ describe Projects::UpdateRepositoryStorageService do
.with(project.wiki.repository.raw).and_return(false) .with(project.wiki.repository.raw).and_return(false)
expect(GitlabShellWorker).not_to receive(:perform_async) expect(GitlabShellWorker).not_to receive(:perform_async)
subject.execute('b') subject.execute('test_second_storage')
expect(project).not_to be_repository_read_only expect(project).not_to be_repository_read_only
expect(project.repository_storage).to eq('a') expect(project.repository_storage).to eq('default')
end end
end end
end end
......
...@@ -294,17 +294,7 @@ module Gitlab ...@@ -294,17 +294,7 @@ module Gitlab
# add_namespace("default", "gitlab") # add_namespace("default", "gitlab")
# #
def add_namespace(storage, name) def add_namespace(storage, name)
Gitlab::GitalyClient.migrate(:add_namespace, Gitlab::GitalyClient::NamespaceService.new(storage).add(name)
status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |enabled|
if enabled
Gitlab::GitalyClient::NamespaceService.new(storage).add(name)
else
path = full_path(storage, name)
FileUtils.mkdir_p(path, mode: 0770) unless exists?(storage, name)
end
end
rescue Errno::EEXIST => e
Rails.logger.warn("Directory exists as a file: #{e} at: #{path}")
rescue GRPC::InvalidArgument => e rescue GRPC::InvalidArgument => e
raise ArgumentError, e.message raise ArgumentError, e.message
end end
...@@ -316,14 +306,7 @@ module Gitlab ...@@ -316,14 +306,7 @@ module Gitlab
# rm_namespace("default", "gitlab") # rm_namespace("default", "gitlab")
# #
def rm_namespace(storage, name) def rm_namespace(storage, name)
Gitlab::GitalyClient.migrate(:remove_namespace, Gitlab::GitalyClient::NamespaceService.new(storage).remove(name)
status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |enabled|
if enabled
Gitlab::GitalyClient::NamespaceService.new(storage).remove(name)
else
FileUtils.rm_r(full_path(storage, name), force: true)
end
end
rescue GRPC::InvalidArgument => e rescue GRPC::InvalidArgument => e
raise ArgumentError, e.message raise ArgumentError, e.message
end end
...@@ -335,17 +318,7 @@ module Gitlab ...@@ -335,17 +318,7 @@ module Gitlab
# mv_namespace("/path/to/storage", "gitlab", "gitlabhq") # mv_namespace("/path/to/storage", "gitlab", "gitlabhq")
# #
def mv_namespace(storage, old_name, new_name) def mv_namespace(storage, old_name, new_name)
Gitlab::GitalyClient.migrate(:rename_namespace, Gitlab::GitalyClient::NamespaceService.new(storage).rename(old_name, new_name)
status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |enabled|
if enabled
Gitlab::GitalyClient::NamespaceService.new(storage)
.rename(old_name, new_name)
else
break false if exists?(storage, new_name) || !exists?(storage, old_name)
FileUtils.mv(full_path(storage, old_name), full_path(storage, new_name))
end
end
rescue GRPC::InvalidArgument rescue GRPC::InvalidArgument
false false
end end
...@@ -370,17 +343,8 @@ module Gitlab ...@@ -370,17 +343,8 @@ module Gitlab
# exists?(storage, 'gitlab') # exists?(storage, 'gitlab')
# exists?(storage, 'gitlab/cookies.git') # exists?(storage, 'gitlab/cookies.git')
# #
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/385
def exists?(storage, dir_name) def exists?(storage, dir_name)
Gitlab::GitalyClient.migrate(:namespace_exists, Gitlab::GitalyClient::NamespaceService.new(storage).exists?(dir_name)
status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |enabled|
if enabled
Gitlab::GitalyClient::NamespaceService.new(storage)
.exists?(dir_name)
else
File.exist?(full_path(storage, dir_name))
end
end
end end
protected protected
......
...@@ -19,7 +19,7 @@ feature 'Admin uses repository checks' do ...@@ -19,7 +19,7 @@ feature 'Admin uses repository checks' do
expect(page).to have_content('Repository check was triggered') expect(page).to have_content('Repository check was triggered')
end end
scenario 'to see a single failed repository check' do scenario 'to see a single failed repository check', :js do
project = create(:project) project = create(:project)
project.update_columns( project.update_columns(
last_repository_check_failed: true, last_repository_check_failed: true,
......
...@@ -252,9 +252,10 @@ feature 'Issues > User uses quick actions', :js do ...@@ -252,9 +252,10 @@ feature 'Issues > User uses quick actions', :js do
end end
context 'when the project is valid but the user not authorized' do context 'when the project is valid but the user not authorized' do
let(:project_unauthorized) {create(:project, :public)} let(:project_unauthorized) { create(:project, :public) }
before do before do
gitlab_sign_out
sign_in(user) sign_in(user)
visit project_issue_path(project, issue) visit project_issue_path(project, issue)
end end
...@@ -269,6 +270,7 @@ feature 'Issues > User uses quick actions', :js do ...@@ -269,6 +270,7 @@ feature 'Issues > User uses quick actions', :js do
context 'when the project is invalid' do context 'when the project is invalid' do
before do before do
gitlab_sign_out
sign_in(user) sign_in(user)
visit project_issue_path(project, issue) visit project_issue_path(project, issue)
end end
......
import Vue from 'vue'; import Vue from 'vue';
import wipComponent from '~/vue_merge_request_widget/components/states/mr_widget_wip'; import WorkInProgress from '~/vue_merge_request_widget/components/states/work_in_progress.vue';
import eventHub from '~/vue_merge_request_widget/event_hub'; import eventHub from '~/vue_merge_request_widget/event_hub';
const createComponent = () => { const createComponent = () => {
const Component = Vue.extend(wipComponent); const Component = Vue.extend(WorkInProgress);
const mr = { const mr = {
title: 'The best MR ever', title: 'The best MR ever',
removeWIPPath: '/path/to/remove/wip', removeWIPPath: '/path/to/remove/wip',
...@@ -17,10 +17,10 @@ const createComponent = () => { ...@@ -17,10 +17,10 @@ const createComponent = () => {
}); });
}; };
describe('MRWidgetWIP', () => { describe('Wip', () => {
describe('props', () => { describe('props', () => {
it('should have props', () => { it('should have props', () => {
const { mr, service } = wipComponent.props; const { mr, service } = WorkInProgress.props;
expect(mr.type instanceof Object).toBeTruthy(); expect(mr.type instanceof Object).toBeTruthy();
expect(mr.required).toBeTruthy(); expect(mr.required).toBeTruthy();
......
...@@ -219,7 +219,7 @@ describe MergeRequests::MergeService do ...@@ -219,7 +219,7 @@ describe MergeRequests::MergeService do
service.execute(merge_request) service.execute(merge_request)
expect(merge_request.merge_error).to include(error_message) expect(merge_request.merge_error).to include('Something went wrong during merge')
expect(Rails.logger).to have_received(:error).with(a_string_matching(error_message)) expect(Rails.logger).to have_received(:error).with(a_string_matching(error_message))
end end
...@@ -231,7 +231,7 @@ describe MergeRequests::MergeService do ...@@ -231,7 +231,7 @@ describe MergeRequests::MergeService do
service.execute(merge_request) service.execute(merge_request)
expect(merge_request.merge_error).to include(error_message) expect(merge_request.merge_error).to include('Something went wrong during merge pre-receive hook')
expect(Rails.logger).to have_received(:error).with(a_string_matching(error_message)) expect(Rails.logger).to have_received(:error).with(a_string_matching(error_message))
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment