Commit 8b0ec861 authored by Valery Sizov's avatar Valery Sizov

Merge branch 'ce_upstream'

parents 691b0e8d 430f7da3
import autosize from 'vendor/autosize'; import autosize from 'vendor/autosize';
$(() => { document.addEventListener('DOMContentLoaded', () => {
const $fields = $('.js-autosize'); const autosizeEls = document.querySelectorAll('.js-autosize');
$fields.on('autosize:resized', function resized() { autosize(autosizeEls);
const $field = $(this); autosize.update(autosizeEls);
$field.data('height', $field.outerHeight());
});
$fields.on('resize.autosize', function resize() {
const $field = $(this);
if ($field.data('height') !== $field.outerHeight()) {
$field.data('height', $field.outerHeight());
autosize.destroy($field);
$field.css('max-height', window.outerHeight);
}
});
autosize($fields);
autosize.update($fields);
$fields.css('resize', 'vertical');
}); });
...@@ -33,3 +33,20 @@ ...@@ -33,3 +33,20 @@
font-weight: normal; font-weight: normal;
} }
} }
.admin-runner-btn-group-cell {
min-width: 150px;
.btn-sm {
padding: 4px 9px;
}
.btn-default {
color: $gl-text-color-secondary;
}
.fa-pause,
.fa-play {
font-size: 11px;
}
}
...@@ -103,8 +103,12 @@ module Routable ...@@ -103,8 +103,12 @@ module Routable
def full_path def full_path
return uncached_full_path unless RequestStore.active? return uncached_full_path unless RequestStore.active?
key = "routable/full_path/#{self.class.name}/#{self.id}" RequestStore[full_path_key] ||= uncached_full_path
RequestStore[key] ||= uncached_full_path end
def expires_full_path_cache
RequestStore.delete(full_path_key) if RequestStore.active?
@full_path = nil
end end
def build_full_path def build_full_path
...@@ -135,6 +139,10 @@ module Routable ...@@ -135,6 +139,10 @@ module Routable
path_changed? || parent_changed? path_changed? || parent_changed?
end end
def full_path_key
@full_path_key ||= "routable/full_path/#{self.class.name}/#{self.id}"
end
def build_full_name def build_full_name
if parent && name if parent && name
parent.human_name + ' / ' + name parent.human_name + ' / ' + name
......
...@@ -977,6 +977,7 @@ class Project < ActiveRecord::Base ...@@ -977,6 +977,7 @@ class Project < ActiveRecord::Base
begin begin
gitlab_shell.mv_repository(repository_storage_path, "#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki") gitlab_shell.mv_repository(repository_storage_path, "#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki")
send_move_instructions(old_path_with_namespace) send_move_instructions(old_path_with_namespace)
expires_full_path_cache
@old_path_with_namespace = old_path_with_namespace @old_path_with_namespace = old_path_with_namespace
...@@ -1087,21 +1088,21 @@ class Project < ActiveRecord::Base ...@@ -1087,21 +1088,21 @@ class Project < ActiveRecord::Base
merge_requests.where(source_project_id: self.id) merge_requests.where(source_project_id: self.id)
end end
def create_repository def create_repository(force: false)
# Forked import is handled asynchronously # Forked import is handled asynchronously
unless forked? return if forked? && !force
if gitlab_shell.add_repository(repository_storage_path, path_with_namespace)
repository.after_create if gitlab_shell.add_repository(repository_storage_path, path_with_namespace)
true repository.after_create
else true
errors.add(:base, 'Failed to create repository via gitlab-shell') else
false errors.add(:base, 'Failed to create repository via gitlab-shell')
end false
end end
end end
def ensure_repository def ensure_repository
create_repository unless repository_exists? create_repository(force: true) unless repository_exists?
end end
def repository_exists? def repository_exists?
......
...@@ -78,6 +78,7 @@ module Projects ...@@ -78,6 +78,7 @@ module Projects
Gitlab::PagesTransfer.new.move_project(project.path, @old_namespace.full_path, @new_namespace.full_path) Gitlab::PagesTransfer.new.move_project(project.path, @old_namespace.full_path, @new_namespace.full_path)
project.old_path_with_namespace = @old_path project.old_path_with_namespace = @old_path
project.expires_full_path_cache
execute_system_hooks execute_system_hooks
end end
......
...@@ -32,13 +32,16 @@ ...@@ -32,13 +32,16 @@
#{time_ago_in_words(runner.contacted_at)} ago #{time_ago_in_words(runner.contacted_at)} ago
- else - else
Never Never
%td %td.admin-runner-btn-group-cell
.pull-right .pull-right.btn-group
= link_to 'Edit', admin_runner_path(runner), class: 'btn btn-sm' = link_to admin_runner_path(runner), class: 'btn btn-sm btn-default has-tooltip', title: 'Edit', ref: 'tooltip', aria: { label: 'Edit' }, data: { placement: 'top', container: 'body'} do
= icon('pencil')
&nbsp; &nbsp;
- if runner.active? - if runner.active?
= link_to 'Pause', [:pause, :admin, runner], data: { confirm: "Are you sure?" }, method: :get, class: 'btn btn-danger btn-sm' = link_to [:pause, :admin, runner], method: :get, class: 'btn btn-sm btn-default has-tooltip', title: 'Pause', ref: 'tooltip', aria: { label: 'Pause' }, data: { placement: 'top', container: 'body', confirm: "Are you sure?" } do
= icon('pause')
- else - else
= link_to 'Resume', [:resume, :admin, runner], method: :get, class: 'btn btn-success btn-sm' = link_to [:resume, :admin, runner], method: :get, class: 'btn btn-default btn-sm has-tooltip', title: 'Resume', ref: 'tooltip', aria: { label: 'Resume' }, data: { placement: 'top', container: 'body'} do
= link_to 'Remove', [:admin, runner], data: { confirm: "Are you sure?" }, method: :delete, class: 'btn btn-danger btn-sm' = icon('play')
= link_to [:admin, runner], method: :delete, class: 'btn btn-danger btn-sm has-tooltip', title: 'Remove', ref: 'tooltip', aria: { label: 'Remove' }, data: { placement: 'top', container: 'body', confirm: "Are you sure?" } do
= icon('remove')
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
%div %div
- if Gitlab::Recaptcha.enabled? - if Gitlab::Recaptcha.enabled?
= recaptcha_tags = recaptcha_tags
%div .submit-container
= f.submit "Register", class: "btn-register btn" = f.submit "Register", class: "btn-register btn"
.clearfix.submit-container .clearfix.submit-container
%p %p
......
...@@ -7,10 +7,9 @@ ...@@ -7,10 +7,9 @@
.form-group .form-group
.col-sm-10.col-sm-offset-2 .col-sm-10.col-sm-offset-2
.checkbox .checkbox
- initial_checkbox_value = issuable.merge_params.key?('force_remove_source_branch') ? issuable.force_remove_source_branch? : true
= label_tag 'merge_request[force_remove_source_branch]' do = label_tag 'merge_request[force_remove_source_branch]' do
= hidden_field_tag 'merge_request[force_remove_source_branch]', '0', id: nil = hidden_field_tag 'merge_request[force_remove_source_branch]', '0', id: nil
= check_box_tag 'merge_request[force_remove_source_branch]', '1', initial_checkbox_value = check_box_tag 'merge_request[force_remove_source_branch]', '1', issuable.force_remove_source_branch?
Remove source branch when merge request is accepted. Remove source branch when merge request is accepted.
= render 'shared/issuable/form/ee/squash_merge_param', issuable: issuable = render 'shared/issuable/form/ee/squash_merge_param', issuable: issuable
---
title: Fix spacing on runner buttons.
merge_request: !12535
author:
---
title: Set default for Remove source branch to false.
merge_request: !12576
author:
---
title: Rename duplicated variables with the same key for projects. Add environment_scope
column to variables and add unique constraint to make sure that no variables could
be created with the same key within a project
merge_request: 12363
author:
---
title: Expires full_path cache after a repository is renamed/transferred
merge_request:
author:
---
title: Make Project#ensure_repository force create a repo
merge_request:
author:
...@@ -93,7 +93,7 @@ For example, suppose we have a UX team with an Issue Board that contains: ...@@ -93,7 +93,7 @@ For example, suppose we have a UX team with an Issue Board that contains:
- **Doing** - **Doing**
- **Frontend** - **Frontend**
When done with something, they move the card to **Frontend**. The Frontend team's board looks like: When done with something, they move the card to **Frontend**. The Frontend team's board looks like:
- **Frontend** - **Frontend**
- **Doing** - **Doing**
...@@ -108,8 +108,7 @@ Cards finished by the UX team will automatically appear in the **Frontend** colu ...@@ -108,8 +108,7 @@ Cards finished by the UX team will automatically appear in the **Frontend** colu
> >
>- For a real use case, please check why >- For a real use case, please check why
[Codepen decided to adopt Issue Boards](https://about.gitlab.com/2017/01/27/codepen-welcome-to-gitlab/#project-management-everything-in-one-place) [Codepen decided to adopt Issue Boards](https://about.gitlab.com/2017/01/27/codepen-welcome-to-gitlab/#project-management-everything-in-one-place)
to improve their workflow with to improve their workflow with multiple boards.
multiple boards.
## Issue Board terminology ## Issue Board terminology
......
...@@ -2,6 +2,8 @@ require 'securerandom' ...@@ -2,6 +2,8 @@ require 'securerandom'
module Gitlab module Gitlab
class Shell class Shell
GITLAB_SHELL_ENV_VARS = %w(GIT_TERMINAL_PROMPT).freeze
Error = Class.new(StandardError) Error = Class.new(StandardError)
KeyAdder = Struct.new(:io) do KeyAdder = Struct.new(:io) do
...@@ -67,8 +69,8 @@ module Gitlab ...@@ -67,8 +69,8 @@ module Gitlab
# add_repository("/path/to/storage", "gitlab/gitlab-ci") # add_repository("/path/to/storage", "gitlab/gitlab-ci")
# #
def add_repository(storage, name) def add_repository(storage, name)
Gitlab::Utils.system_silent([gitlab_shell_projects_path, gitlab_shell_fast_execute([gitlab_shell_projects_path,
'add-project', storage, "#{name}.git"]) 'add-project', storage, "#{name}.git"])
end end
# Import repository # Import repository
...@@ -82,10 +84,9 @@ module Gitlab ...@@ -82,10 +84,9 @@ module Gitlab
def import_repository(storage, name, url) def import_repository(storage, name, url)
# Timeout should be less than 900 ideally, to prevent the memory killer # Timeout should be less than 900 ideally, to prevent the memory killer
# to silently kill the process without knowing we are timing out here. # to silently kill the process without knowing we are timing out here.
output, status = Popen.popen([gitlab_shell_projects_path, 'import-project', cmd = [gitlab_shell_projects_path, 'import-project',
storage, "#{name}.git", url, "#{Gitlab.config.gitlab_shell.git_timeout}"]) storage, "#{name}.git", url, "#{Gitlab.config.gitlab_shell.git_timeout}"]
raise Error, output unless status.zero? gitlab_shell_fast_execute_raise_error(cmd)
true
end end
def list_remote_tags(storage, name, remote) def list_remote_tags(storage, name, remote)
...@@ -131,9 +132,7 @@ module Gitlab ...@@ -131,9 +132,7 @@ module Gitlab
args << '--force' if forced args << '--force' if forced
args << '--no-tags' if no_tags args << '--no-tags' if no_tags
output, status = Popen.popen(args) gitlab_shell_fast_execute_raise_error(args)
raise Error, output unless status.zero?
true
end end
# Move repository # Move repository
...@@ -145,8 +144,8 @@ module Gitlab ...@@ -145,8 +144,8 @@ module Gitlab
# mv_repository("/path/to/storage", "gitlab/gitlab-ci", "randx/gitlab-ci-new") # mv_repository("/path/to/storage", "gitlab/gitlab-ci", "randx/gitlab-ci-new")
# #
def mv_repository(storage, path, new_path) def mv_repository(storage, path, new_path)
Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'mv-project', gitlab_shell_fast_execute([gitlab_shell_projects_path, 'mv-project',
storage, "#{path}.git", "#{new_path}.git"]) storage, "#{path}.git", "#{new_path}.git"])
end end
# Move repository storage # Move repository storage
...@@ -173,9 +172,9 @@ module Gitlab ...@@ -173,9 +172,9 @@ module Gitlab
# fork_repository("/path/to/forked_from/storage", "gitlab/gitlab-ci", "/path/to/forked_to/storage", "randx") # fork_repository("/path/to/forked_from/storage", "gitlab/gitlab-ci", "/path/to/forked_to/storage", "randx")
# #
def fork_repository(forked_from_storage, path, forked_to_storage, fork_namespace) def fork_repository(forked_from_storage, path, forked_to_storage, fork_namespace)
Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'fork-project', gitlab_shell_fast_execute([gitlab_shell_projects_path, 'fork-project',
forked_from_storage, "#{path}.git", forked_to_storage, forked_from_storage, "#{path}.git", forked_to_storage,
fork_namespace]) fork_namespace])
end end
# Remove repository from file system # Remove repository from file system
...@@ -187,8 +186,8 @@ module Gitlab ...@@ -187,8 +186,8 @@ module Gitlab
# remove_repository("/path/to/storage", "gitlab/gitlab-ci") # remove_repository("/path/to/storage", "gitlab/gitlab-ci")
# #
def remove_repository(storage, name) def remove_repository(storage, name)
Gitlab::Utils.system_silent([gitlab_shell_projects_path, gitlab_shell_fast_execute([gitlab_shell_projects_path,
'rm-project', storage, "#{name}.git"]) 'rm-project', storage, "#{name}.git"])
end end
# Add new key to gitlab-shell # Add new key to gitlab-shell
...@@ -199,8 +198,8 @@ module Gitlab ...@@ -199,8 +198,8 @@ module Gitlab
def add_key(key_id, key_content) def add_key(key_id, key_content)
return unless self.authorized_keys_enabled? return unless self.authorized_keys_enabled?
Gitlab::Utils.system_silent([gitlab_shell_keys_path, gitlab_shell_fast_execute([gitlab_shell_keys_path,
'add-key', key_id, self.class.strip_key(key_content)]) 'add-key', key_id, self.class.strip_key(key_content)])
end end
# Batch-add keys to authorized_keys # Batch-add keys to authorized_keys
...@@ -225,7 +224,7 @@ module Gitlab ...@@ -225,7 +224,7 @@ module Gitlab
args = [gitlab_shell_keys_path, 'rm-key', key_id] args = [gitlab_shell_keys_path, 'rm-key', key_id]
args << key_content if key_content args << key_content if key_content
Gitlab::Utils.system_silent(args) gitlab_shell_fast_execute(args)
end end
# Remove all ssh keys from gitlab shell # Remove all ssh keys from gitlab shell
...@@ -236,7 +235,7 @@ module Gitlab ...@@ -236,7 +235,7 @@ module Gitlab
def remove_all_keys def remove_all_keys
return unless self.authorized_keys_enabled? return unless self.authorized_keys_enabled?
Gitlab::Utils.system_silent([gitlab_shell_keys_path, 'clear']) gitlab_shell_fast_execute([gitlab_shell_keys_path, 'clear'])
end end
# Remove ssh keys from gitlab shell that are not in the DB # Remove ssh keys from gitlab shell that are not in the DB
...@@ -424,5 +423,31 @@ module Gitlab ...@@ -424,5 +423,31 @@ module Gitlab
current_application_settings.authorized_keys_enabled current_application_settings.authorized_keys_enabled
end end
private
def gitlab_shell_fast_execute(cmd)
output, status = gitlab_shell_fast_execute_helper(cmd)
return true if status.zero?
Rails.logger.error("gitlab-shell failed with error #{status}: #{output}")
false
end
def gitlab_shell_fast_execute_raise_error(cmd)
output, status = gitlab_shell_fast_execute_helper(cmd)
raise Error, output unless status.zero?
true
end
def gitlab_shell_fast_execute_helper(cmd)
vars = ENV.to_h.slice(*GITLAB_SHELL_ENV_VARS)
# Don't pass along the entire parent environment to prevent gitlab-shell
# from wasting I/O by searching through GEM_PATH
Bundler.with_original_env { Popen.popen(cmd, nil, vars) }
end
end end
end end
require 'spec_helper' require 'spec_helper'
feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do feature 'Projects > Wiki > User creates wiki page', :js do
let(:user) { create(:user) } let(:user) { create(:user) }
background do background do
project.team << [user, :master] project.team << [user, :master]
gitlab_sign_in(user) sign_in(user)
visit project_path(project) visit project_path(project)
find('.shortcuts-wiki').trigger('click')
end end
context 'in the user namespace' do context 'in the user namespace' do
let(:project) { create(:project, namespace: user.namespace) } let(:project) { create(:project, namespace: user.namespace) }
context 'when wiki is empty' do context 'when wiki is empty' do
before do
find('.shortcuts-wiki').trigger('click')
end
scenario 'commit message field has value "Create home"' do scenario 'commit message field has value "Create home"' do
expect(page).to have_field('wiki[message]', with: 'Create home') expect(page).to have_field('wiki[message]', with: 'Create home')
end end
...@@ -67,10 +70,11 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do ...@@ -67,10 +70,11 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do
context 'when wiki is not empty' do context 'when wiki is not empty' do
before do before do
WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute
find('.shortcuts-wiki').trigger('click')
end end
context 'via the "new wiki page" page' do context 'via the "new wiki page" page' do
scenario 'when the wiki page has a single word name', js: true do scenario 'when the wiki page has a single word name' do
click_link 'New page' click_link 'New page'
page.within '#modal-new-wiki' do page.within '#modal-new-wiki' do
...@@ -91,7 +95,7 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do ...@@ -91,7 +95,7 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do
expect(page).to have_content('My awesome wiki!') expect(page).to have_content('My awesome wiki!')
end end
scenario 'when the wiki page has spaces in the name', js: true do scenario 'when the wiki page has spaces in the name' do
click_link 'New page' click_link 'New page'
page.within '#modal-new-wiki' do page.within '#modal-new-wiki' do
...@@ -112,7 +116,7 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do ...@@ -112,7 +116,7 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do
expect(page).to have_content('My awesome wiki!') expect(page).to have_content('My awesome wiki!')
end end
scenario 'when the wiki page has hyphens in the name', js: true do scenario 'when the wiki page has hyphens in the name' do
click_link 'New page' click_link 'New page'
page.within '#modal-new-wiki' do page.within '#modal-new-wiki' do
...@@ -134,7 +138,7 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do ...@@ -134,7 +138,7 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do
end end
end end
scenario 'content has autocomplete', :js do scenario 'content has autocomplete' do
click_link 'New page' click_link 'New page'
page.within '#modal-new-wiki' do page.within '#modal-new-wiki' do
...@@ -156,6 +160,10 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do ...@@ -156,6 +160,10 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do
let(:project) { create(:project, namespace: create(:group, :public)) } let(:project) { create(:project, namespace: create(:group, :public)) }
context 'when wiki is empty' do context 'when wiki is empty' do
before do
find('.shortcuts-wiki').trigger('click')
end
scenario 'commit message field has value "Create home"' do scenario 'commit message field has value "Create home"' do
expect(page).to have_field('wiki[message]', with: 'Create home') expect(page).to have_field('wiki[message]', with: 'Create home')
end end
...@@ -175,9 +183,10 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do ...@@ -175,9 +183,10 @@ feature 'Projects > Wiki > User creates wiki page', js: true, feature: true do
context 'when wiki is not empty' do context 'when wiki is not empty' do
before do before do
WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute
find('.shortcuts-wiki').trigger('click')
end end
scenario 'via the "new wiki page" page', js: true do scenario 'via the "new wiki page" page' do
click_link 'New page' click_link 'New page'
page.within '#modal-new-wiki' do page.within '#modal-new-wiki' do
......
...@@ -32,6 +32,17 @@ describe 'Gitlab::Popen', lib: true, no_db: true do ...@@ -32,6 +32,17 @@ describe 'Gitlab::Popen', lib: true, no_db: true do
end end
end end
context 'with custom options' do
let(:vars) { { 'foobar' => 123, 'PWD' => path } }
let(:options) { { chdir: path } }
it 'calls popen3 with the provided environment variables' do
expect(Open3).to receive(:popen3).with(vars, 'ls', options)
@output, @status = @klass.new.popen(%w(ls), path, { 'foobar' => 123 })
end
end
context 'without a directory argument' do context 'without a directory argument' do
before do before do
@output, @status = @klass.new.popen(%w(ls)) @output, @status = @klass.new.popen(%w(ls))
...@@ -45,7 +56,7 @@ describe 'Gitlab::Popen', lib: true, no_db: true do ...@@ -45,7 +56,7 @@ describe 'Gitlab::Popen', lib: true, no_db: true do
before do before do
@output, @status = @klass.new.popen(%w[cat]) { |stdin| stdin.write 'hello' } @output, @status = @klass.new.popen(%w[cat]) { |stdin| stdin.write 'hello' }
end end
it { expect(@status).to be_zero } it { expect(@status).to be_zero }
it { expect(@output).to eq('hello') } it { expect(@output).to eq('hello') }
end end
......
...@@ -4,6 +4,7 @@ require 'stringio' ...@@ -4,6 +4,7 @@ require 'stringio'
describe Gitlab::Shell, lib: true do describe Gitlab::Shell, lib: true do
let(:project) { double('Project', id: 7, path: 'diaspora') } let(:project) { double('Project', id: 7, path: 'diaspora') }
let(:gitlab_shell) { Gitlab::Shell.new } let(:gitlab_shell) { Gitlab::Shell.new }
let(:popen_vars) { { 'GIT_TERMINAL_PROMPT' => ENV['GIT_TERMINAL_PROMPT'] } }
before do before do
allow(Project).to receive(:find).and_return(project) allow(Project).to receive(:find).and_return(project)
...@@ -56,8 +57,9 @@ describe Gitlab::Shell, lib: true do ...@@ -56,8 +57,9 @@ describe Gitlab::Shell, lib: true do
describe '#mv_repository' do describe '#mv_repository' do
it 'executes the command' do it 'executes the command' do
expect(Gitlab::Utils).to receive(:system_silent) expect(gitlab_shell).to receive(:gitlab_shell_fast_execute).with(
.with([projects_path, 'mv-project', 'storage/path', 'project/path.git', 'new/path.git']) [projects_path, 'mv-project', 'storage/path', 'project/path.git', 'new/path.git']
)
gitlab_shell.mv_repository('storage/path', 'project/path', 'new/path') gitlab_shell.mv_repository('storage/path', 'project/path', 'new/path')
end end
end end
...@@ -70,22 +72,6 @@ describe Gitlab::Shell, lib: true do ...@@ -70,22 +72,6 @@ describe Gitlab::Shell, lib: true do
end end
end end
describe '#fetch_remote' do
it 'executes the command' do
expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'fetch-remote', 'current/storage', 'project/path.git', 'new/storage', '800']).and_return([nil, 0])
expect(gitlab_shell.fetch_remote('current/storage', 'project/path', 'new/storage')).to be true
end
it 'fails to execute the command' do
expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'fetch-remote', 'current/storage', 'project/path.git', 'new/storage', '800']).and_return(["error", 1])
expect { gitlab_shell.fetch_remote('current/storage', 'project/path', 'new/storage') }.to raise_error(Gitlab::Shell::Error, "error")
end
end
describe '#push_remote_branches' do describe '#push_remote_branches' do
it 'executes the command' do it 'executes the command' do
expect(Gitlab::Popen).to receive(:popen) expect(Gitlab::Popen).to receive(:popen)
...@@ -107,7 +93,7 @@ describe Gitlab::Shell, lib: true do ...@@ -107,7 +93,7 @@ describe Gitlab::Shell, lib: true do
context 'when authorized_keys_enabled is true' do context 'when authorized_keys_enabled is true' do
it 'removes trailing garbage' do it 'removes trailing garbage' do
allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path) allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
expect(Gitlab::Utils).to receive(:system_silent).with( expect(gitlab_shell).to receive(:gitlab_shell_fast_execute).with(
[:gitlab_shell_keys_path, 'add-key', 'key-123', 'ssh-rsa foobar'] [:gitlab_shell_keys_path, 'add-key', 'key-123', 'ssh-rsa foobar']
) )
...@@ -134,7 +120,7 @@ describe Gitlab::Shell, lib: true do ...@@ -134,7 +120,7 @@ describe Gitlab::Shell, lib: true do
it 'removes trailing garbage' do it 'removes trailing garbage' do
allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path) allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
expect(Gitlab::Utils).to receive(:system_silent).with( expect(gitlab_shell).to receive(:gitlab_shell_fast_execute).with(
[:gitlab_shell_keys_path, 'add-key', 'key-123', 'ssh-rsa foobar'] [:gitlab_shell_keys_path, 'add-key', 'key-123', 'ssh-rsa foobar']
) )
...@@ -187,7 +173,7 @@ describe Gitlab::Shell, lib: true do ...@@ -187,7 +173,7 @@ describe Gitlab::Shell, lib: true do
context 'when authorized_keys_enabled is true' do context 'when authorized_keys_enabled is true' do
it 'removes trailing garbage' do it 'removes trailing garbage' do
allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path) allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
expect(Gitlab::Utils).to receive(:system_silent).with( expect(gitlab_shell).to receive(:gitlab_shell_fast_execute).with(
[:gitlab_shell_keys_path, 'rm-key', 'key-123', 'ssh-rsa foobar'] [:gitlab_shell_keys_path, 'rm-key', 'key-123', 'ssh-rsa foobar']
) )
...@@ -201,7 +187,7 @@ describe Gitlab::Shell, lib: true do ...@@ -201,7 +187,7 @@ describe Gitlab::Shell, lib: true do
end end
it 'does nothing' do it 'does nothing' do
expect(Gitlab::Utils).not_to receive(:system_silent) expect(gitlab_shell).not_to receive(:gitlab_shell_fast_execute)
gitlab_shell.remove_key('key-123', 'ssh-rsa foobar') gitlab_shell.remove_key('key-123', 'ssh-rsa foobar')
end end
...@@ -214,7 +200,7 @@ describe Gitlab::Shell, lib: true do ...@@ -214,7 +200,7 @@ describe Gitlab::Shell, lib: true do
it 'removes trailing garbage' do it 'removes trailing garbage' do
allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path) allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
expect(Gitlab::Utils).to receive(:system_silent).with( expect(gitlab_shell).to receive(:gitlab_shell_fast_execute).with(
[:gitlab_shell_keys_path, 'rm-key', 'key-123', 'ssh-rsa foobar'] [:gitlab_shell_keys_path, 'rm-key', 'key-123', 'ssh-rsa foobar']
) )
...@@ -225,7 +211,7 @@ describe Gitlab::Shell, lib: true do ...@@ -225,7 +211,7 @@ describe Gitlab::Shell, lib: true do
context 'when key content is not given' do context 'when key content is not given' do
it 'calls rm-key with only one argument' do it 'calls rm-key with only one argument' do
allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path) allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
expect(Gitlab::Utils).to receive(:system_silent).with( expect(gitlab_shell).to receive(:gitlab_shell_fast_execute).with(
[:gitlab_shell_keys_path, 'rm-key', 'key-123'] [:gitlab_shell_keys_path, 'rm-key', 'key-123']
) )
...@@ -238,7 +224,7 @@ describe Gitlab::Shell, lib: true do ...@@ -238,7 +224,7 @@ describe Gitlab::Shell, lib: true do
context 'when authorized_keys_enabled is true' do context 'when authorized_keys_enabled is true' do
it 'removes trailing garbage' do it 'removes trailing garbage' do
allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path) allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
expect(Gitlab::Utils).to receive(:system_silent).with([:gitlab_shell_keys_path, 'clear']) expect(gitlab_shell).to receive(:gitlab_shell_fast_execute).with([:gitlab_shell_keys_path, 'clear'])
gitlab_shell.remove_all_keys gitlab_shell.remove_all_keys
end end
...@@ -250,7 +236,7 @@ describe Gitlab::Shell, lib: true do ...@@ -250,7 +236,7 @@ describe Gitlab::Shell, lib: true do
end end
it 'does nothing' do it 'does nothing' do
expect(Gitlab::Utils).not_to receive(:system_silent) expect(gitlab_shell).not_to receive(:gitlab_shell_fast_execute)
gitlab_shell.remove_all_keys gitlab_shell.remove_all_keys
end end
...@@ -263,7 +249,9 @@ describe Gitlab::Shell, lib: true do ...@@ -263,7 +249,9 @@ describe Gitlab::Shell, lib: true do
it 'removes trailing garbage' do it 'removes trailing garbage' do
allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path) allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path)
expect(Gitlab::Utils).to receive(:system_silent).with([:gitlab_shell_keys_path, 'clear']) expect(gitlab_shell).to receive(:gitlab_shell_fast_execute).with(
[:gitlab_shell_keys_path, 'clear']
)
gitlab_shell.remove_all_keys gitlab_shell.remove_all_keys
end end
...@@ -448,17 +436,91 @@ describe Gitlab::Shell, lib: true do ...@@ -448,17 +436,91 @@ describe Gitlab::Shell, lib: true do
allow(Gitlab.config.gitlab_shell).to receive(:git_timeout).and_return(800) allow(Gitlab.config.gitlab_shell).to receive(:git_timeout).and_return(800)
end end
describe '#add_repository' do
it 'returns true when the command succeeds' do
expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'add-project', 'current/storage', 'project/path.git'],
nil, popen_vars).and_return([nil, 0])
expect(gitlab_shell.add_repository('current/storage', 'project/path')).to be true
end
it 'returns false when the command fails' do
expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'add-project', 'current/storage', 'project/path.git'],
nil, popen_vars).and_return(["error", 1])
expect(gitlab_shell.add_repository('current/storage', 'project/path')).to be false
end
end
describe '#remove_repository' do
it 'returns true when the command succeeds' do
expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'rm-project', 'current/storage', 'project/path.git'],
nil, popen_vars).and_return([nil, 0])
expect(gitlab_shell.remove_repository('current/storage', 'project/path')).to be true
end
it 'returns false when the command fails' do
expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'rm-project', 'current/storage', 'project/path.git'],
nil, popen_vars).and_return(["error", 1])
expect(gitlab_shell.remove_repository('current/storage', 'project/path')).to be false
end
end
describe '#mv_repository' do
it 'returns true when the command succeeds' do
expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'mv-project', 'current/storage', 'project/path.git', 'project/newpath.git'],
nil, popen_vars).and_return([nil, 0])
expect(gitlab_shell.mv_repository('current/storage', 'project/path', 'project/newpath')).to be true
end
it 'returns false when the command fails' do
expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'mv-project', 'current/storage', 'project/path.git', 'project/newpath.git'],
nil, popen_vars).and_return(["error", 1])
expect(gitlab_shell.mv_repository('current/storage', 'project/path', 'project/newpath')).to be false
end
end
describe '#fork_repository' do
it 'returns true when the command succeeds' do
expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'fork-project', 'current/storage', 'project/path.git', 'new/storage', 'new-namespace'],
nil, popen_vars).and_return([nil, 0])
expect(gitlab_shell.fork_repository('current/storage', 'project/path', 'new/storage', 'new-namespace')).to be true
end
it 'return false when the command fails' do
expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'fork-project', 'current/storage', 'project/path.git', 'new/storage', 'new-namespace'],
nil, popen_vars).and_return(["error", 1])
expect(gitlab_shell.fork_repository('current/storage', 'project/path', 'new/storage', 'new-namespace')).to be false
end
end
describe '#fetch_remote' do describe '#fetch_remote' do
it 'returns true when the command succeeds' do it 'returns true when the command succeeds' do
expect(Gitlab::Popen).to receive(:popen) expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'fetch-remote', 'current/storage', 'project/path.git', 'new/storage', '800']).and_return([nil, 0]) .with([projects_path, 'fetch-remote', 'current/storage', 'project/path.git', 'new/storage', '800'],
nil, popen_vars).and_return([nil, 0])
expect(gitlab_shell.fetch_remote('current/storage', 'project/path', 'new/storage')).to be true expect(gitlab_shell.fetch_remote('current/storage', 'project/path', 'new/storage')).to be true
end end
it 'raises an exception when the command fails' do it 'raises an exception when the command fails' do
expect(Gitlab::Popen).to receive(:popen) expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'fetch-remote', 'current/storage', 'project/path.git', 'new/storage', '800']).and_return(["error", 1]) .with([projects_path, 'fetch-remote', 'current/storage', 'project/path.git', 'new/storage', '800'],
nil, popen_vars).and_return(["error", 1])
expect { gitlab_shell.fetch_remote('current/storage', 'project/path', 'new/storage') }.to raise_error(Gitlab::Shell::Error, "error") expect { gitlab_shell.fetch_remote('current/storage', 'project/path', 'new/storage') }.to raise_error(Gitlab::Shell::Error, "error")
end end
...@@ -467,14 +529,16 @@ describe Gitlab::Shell, lib: true do ...@@ -467,14 +529,16 @@ describe Gitlab::Shell, lib: true do
describe '#import_repository' do describe '#import_repository' do
it 'returns true when the command succeeds' do it 'returns true when the command succeeds' do
expect(Gitlab::Popen).to receive(:popen) expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'import-project', 'current/storage', 'project/path.git', 'https://gitlab.com/gitlab-org/gitlab-ce.git', "800"]).and_return([nil, 0]) .with([projects_path, 'import-project', 'current/storage', 'project/path.git', 'https://gitlab.com/gitlab-org/gitlab-ce.git', "800"],
nil, popen_vars).and_return([nil, 0])
expect(gitlab_shell.import_repository('current/storage', 'project/path', 'https://gitlab.com/gitlab-org/gitlab-ce.git')).to be true expect(gitlab_shell.import_repository('current/storage', 'project/path', 'https://gitlab.com/gitlab-org/gitlab-ce.git')).to be true
end end
it 'raises an exception when the command fails' do it 'raises an exception when the command fails' do
expect(Gitlab::Popen).to receive(:popen) expect(Gitlab::Popen).to receive(:popen)
.with([projects_path, 'import-project', 'current/storage', 'project/path.git', 'https://gitlab.com/gitlab-org/gitlab-ce.git', "800"]).and_return(["error", 1]) .with([projects_path, 'import-project', 'current/storage', 'project/path.git', 'https://gitlab.com/gitlab-org/gitlab-ce.git', "800"],
nil, popen_vars).and_return(["error", 1])
expect { gitlab_shell.import_repository('current/storage', 'project/path', 'https://gitlab.com/gitlab-org/gitlab-ce.git') }.to raise_error(Gitlab::Shell::Error, "error") expect { gitlab_shell.import_repository('current/storage', 'project/path', 'https://gitlab.com/gitlab-org/gitlab-ce.git') }.to raise_error(Gitlab::Shell::Error, "error")
end end
......
...@@ -3,14 +3,13 @@ require 'spec_helper' ...@@ -3,14 +3,13 @@ require 'spec_helper'
describe Ci::Variable, models: true do describe Ci::Variable, models: true do
subject { build(:ci_variable) } subject { build(:ci_variable) }
it { is_expected.to include_module(HasVariable) }
describe 'validations' do describe 'validations' do
# EE # EE
before do before do
stub_licensed_features(variable_environment_scope: true) stub_licensed_features(variable_environment_scope: true)
end end
it { is_expected.to include_module(HasVariable) }
it { is_expected.to validate_uniqueness_of(:key).scoped_to(:project_id, :environment_scope) } it { is_expected.to validate_uniqueness_of(:key).scoped_to(:project_id, :environment_scope) }
end end
......
...@@ -142,6 +142,19 @@ describe Group, 'Routable' do ...@@ -142,6 +142,19 @@ describe Group, 'Routable' do
end end
end end
describe '#expires_full_path_cache' do
context 'with RequestStore active', :request_store do
it 'expires the full_path cache' do
expect(group.full_path).to eq('foo')
group.route.update(path: 'bar', name: 'bar')
group.expires_full_path_cache
expect(group.full_path).to eq('bar')
end
end
end
describe '#full_name' do describe '#full_name' do
let(:group) { create(:group) } let(:group) { create(:group) }
let(:nested_group) { create(:group, parent: group) } let(:nested_group) { create(:group, parent: group) }
......
...@@ -1458,6 +1458,8 @@ describe Project, models: true do ...@@ -1458,6 +1458,8 @@ describe Project, models: true do
expect(project).to receive(:expire_caches_before_rename) expect(project).to receive(:expire_caches_before_rename)
expect(project).to receive(:expires_full_path_cache)
project.rename_repo project.rename_repo
end end
...@@ -1586,7 +1588,7 @@ describe Project, models: true do ...@@ -1586,7 +1588,7 @@ describe Project, models: true do
.with(project.repository_storage_path, project.path_with_namespace) .with(project.repository_storage_path, project.path_with_namespace)
.and_return(true) .and_return(true)
expect(project).to receive(:create_repository) expect(project).to receive(:create_repository).with(force: true)
project.ensure_repository project.ensure_repository
end end
...@@ -1599,6 +1601,19 @@ describe Project, models: true do ...@@ -1599,6 +1601,19 @@ describe Project, models: true do
project.ensure_repository project.ensure_repository
end end
it 'creates the repository if it is a fork' do
expect(project).to receive(:forked?).and_return(true)
allow(project).to receive(:repository_exists?)
.and_return(false)
expect(shell).to receive(:add_repository)
.with(project.repository_storage_path, project.path_with_namespace)
.and_return(true)
project.ensure_repository
end
end end
describe 'handling import URL' do describe 'handling import URL' do
......
...@@ -30,6 +30,12 @@ describe Projects::TransferService, services: true do ...@@ -30,6 +30,12 @@ describe Projects::TransferService, services: true do
transfer_project(project, user, group) transfer_project(project, user, group)
end end
it 'expires full_path cache' do
expect(project).to receive(:expires_full_path_cache)
transfer_project(project, user, group)
end
it 'executes system hooks' do it 'executes system hooks' do
expect_any_instance_of(Projects::TransferService).to receive(:execute_system_hooks) expect_any_instance_of(Projects::TransferService).to receive(:execute_system_hooks)
......
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