Commit 9a7ada02 authored by Valery Sizov's avatar Valery Sizov

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into ce_upstream

parents 51bdfb76 06c7d6f3
...@@ -193,7 +193,7 @@ Style/EmptyLineBetweenDefs: ...@@ -193,7 +193,7 @@ Style/EmptyLineBetweenDefs:
# Don't use several empty lines in a row. # Don't use several empty lines in a row.
Style/EmptyLines: Style/EmptyLines:
Enabled: false Enabled: true
# Keep blank lines around access modifiers. # Keep blank lines around access modifiers.
Style/EmptyLinesAroundAccessModifier: Style/EmptyLinesAroundAccessModifier:
......
...@@ -10,6 +10,7 @@ v 8.10.0 (unreleased) ...@@ -10,6 +10,7 @@ v 8.10.0 (unreleased)
- Display last commit of deleted branch in push events !4699 (winniehell) - Display last commit of deleted branch in push events !4699 (winniehell)
- Apply the trusted_proxies config to the rack request object for use with rack_attack - Apply the trusted_proxies config to the rack request object for use with rack_attack
- Add Sidekiq queue duration to transaction metrics. - Add Sidekiq queue duration to transaction metrics.
- Add a new column `artifacts_size` to table `ci_builds` !4964
- Let Workhorse serve format-patch diffs - Let Workhorse serve format-patch diffs
- Make images fit to the size of the viewport !4810 - Make images fit to the size of the viewport !4810
- Fix check for New Branch button on Issue page !4630 (winniehell) - Fix check for New Branch button on Issue page !4630 (winniehell)
...@@ -31,12 +32,20 @@ v 8.10.0 (unreleased) ...@@ -31,12 +32,20 @@ v 8.10.0 (unreleased)
- Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab - Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab
- Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w) - Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w)
- Add basic system information like memory and disk usage to the admin panel - Add basic system information like memory and disk usage to the admin panel
- Don't garbage collect commits that have related DB records like comments
- More descriptive message for git hooks and file locks
- Handle custom Git hook result in GitLab UI
v 8.9.4 (unreleased)
- Ensure references to private repos aren't shown to logged-out users
v 8.9.5 (unreleased) v 8.9.5 (unreleased)
- Improve the request / withdraw access button. !4860 - Improve the request / withdraw access button. !4860
- Fix assigning shared runners as admins. !4961 - Fix assigning shared runners as admins. !4961
- Show "locked" label for locked runners on runners admin. !4961 - Show "locked" label for locked runners on runners admin. !4961
- Downgrade to Redis 3.2.2 due to massive memory leak with Sidekiq
- Fixes issues importing events in Import/Export. Import/Export version bumped to 0.1.1 - Fixes issues importing events in Import/Export. Import/Export version bumped to 0.1.1
- Fix import button disabled when import process fail due to the namespace already been taken.
- Security: Update RedCloth to 4.3.2 (Takuya Noguchi)
v 8.9.4 v 8.9.4
- Fix privilege escalation issue with OAuth external users. - Fix privilege escalation issue with OAuth external users.
......
...@@ -117,7 +117,7 @@ gem 'html-pipeline', '~> 1.11.0' ...@@ -117,7 +117,7 @@ gem 'html-pipeline', '~> 1.11.0'
gem 'task_list', '~> 1.0.2', require: 'task_list/railtie' gem 'task_list', '~> 1.0.2', require: 'task_list/railtie'
gem 'github-markup', '~> 1.3.1' gem 'github-markup', '~> 1.3.1'
gem 'redcarpet', '~> 3.3.3' gem 'redcarpet', '~> 3.3.3'
gem 'RedCloth', '~> 4.2.9' gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~>3.6' gem 'rdoc', '~>3.6'
gem 'org-ruby', '~> 0.9.12' gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0' gem 'creole', '~> 0.5.0'
...@@ -275,7 +275,7 @@ group :development do ...@@ -275,7 +275,7 @@ group :development do
gem "sdoc", '~> 0.3.20' gem "sdoc", '~> 0.3.20'
# thin instead webrick # thin instead webrick
gem 'thin', '~> 1.6.1' gem 'thin', '~> 1.7.0'
end end
group :development, :test do group :development, :test do
...@@ -287,7 +287,7 @@ group :development, :test do ...@@ -287,7 +287,7 @@ group :development, :test do
gem 'database_cleaner', '~> 1.4.0' gem 'database_cleaner', '~> 1.4.0'
gem 'factory_girl_rails', '~> 4.6.0' gem 'factory_girl_rails', '~> 4.6.0'
gem 'rspec-rails', '~> 3.4.0' gem 'rspec-rails', '~> 3.5.0'
gem 'rspec-retry' gem 'rspec-retry'
gem 'spinach-rails', '~> 0.2.1' gem 'spinach-rails', '~> 0.2.1'
gem 'spinach-rerun-reporter', '~> 0.0.2' gem 'spinach-rerun-reporter', '~> 0.0.2'
......
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
RedCloth (4.2.9) RedCloth (4.3.2)
ace-rails-ap (4.0.2) ace-rails-ap (4.0.2)
actionmailer (4.2.6) actionmailer (4.2.6)
actionpack (= 4.2.6) actionpack (= 4.2.6)
...@@ -578,7 +578,7 @@ GEM ...@@ -578,7 +578,7 @@ GEM
recaptcha (3.0.0) recaptcha (3.0.0)
json json
redcarpet (3.3.3) redcarpet (3.3.3)
redis (3.3.0) redis (3.2.2)
redis-actionpack (4.0.1) redis-actionpack (4.0.1)
actionpack (~> 4) actionpack (~> 4)
redis-rack (~> 1.5.0) redis-rack (~> 1.5.0)
...@@ -609,29 +609,29 @@ GEM ...@@ -609,29 +609,29 @@ GEM
chunky_png chunky_png
rqrcode-rails3 (0.1.7) rqrcode-rails3 (0.1.7)
rqrcode (>= 0.4.2) rqrcode (>= 0.4.2)
rspec (3.4.0) rspec (3.5.0)
rspec-core (~> 3.4.0) rspec-core (~> 3.5.0)
rspec-expectations (~> 3.4.0) rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.4.0) rspec-mocks (~> 3.5.0)
rspec-core (3.4.4) rspec-core (3.5.0)
rspec-support (~> 3.4.0) rspec-support (~> 3.5.0)
rspec-expectations (3.4.0) rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.4.0) rspec-support (~> 3.5.0)
rspec-mocks (3.4.1) rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.4.0) rspec-support (~> 3.5.0)
rspec-rails (3.4.2) rspec-rails (3.5.0)
actionpack (>= 3.0, < 4.3) actionpack (>= 3.0)
activesupport (>= 3.0, < 4.3) activesupport (>= 3.0)
railties (>= 3.0, < 4.3) railties (>= 3.0)
rspec-core (~> 3.4.0) rspec-core (~> 3.5.0)
rspec-expectations (~> 3.4.0) rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.4.0) rspec-mocks (~> 3.5.0)
rspec-support (~> 3.4.0) rspec-support (~> 3.5.0)
rspec-retry (0.4.5) rspec-retry (0.4.5)
rspec-core rspec-core
rspec-support (3.4.1) rspec-support (3.5.0)
rubocop (0.40.0) rubocop (0.40.0)
parser (>= 2.3.1.0, < 3.0) parser (>= 2.3.1.0, < 3.0)
powerpack (~> 0.1) powerpack (~> 0.1)
...@@ -656,8 +656,8 @@ GEM ...@@ -656,8 +656,8 @@ GEM
sanitize (2.1.0) sanitize (2.1.0)
nokogiri (>= 1.4.4) nokogiri (>= 1.4.4)
sass (3.4.22) sass (3.4.22)
sass-rails (5.0.4) sass-rails (5.0.5)
railties (>= 4.0.0, < 5.0) railties (>= 4.0.0, < 6)
sass (~> 3.1) sass (~> 3.1)
sprockets (>= 2.8, < 4.0) sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0) sprockets-rails (>= 2.0, < 4.0)
...@@ -671,9 +671,9 @@ GEM ...@@ -671,9 +671,9 @@ GEM
sdoc (0.3.20) sdoc (0.3.20)
json (>= 1.1.3) json (>= 1.1.3)
rdoc (~> 3.10) rdoc (~> 3.10)
seed-fu (2.3.5) seed-fu (2.3.6)
activerecord (>= 3.1, < 4.3) activerecord (>= 3.1)
activesupport (>= 3.1, < 4.3) activesupport (>= 3.1)
select2-rails (3.5.9.3) select2-rails (3.5.9.3)
thor (~> 0.14) thor (~> 0.14)
sentry-raven (1.1.0) sentry-raven (1.1.0)
...@@ -684,10 +684,11 @@ GEM ...@@ -684,10 +684,11 @@ GEM
rack rack
shoulda-matchers (2.8.0) shoulda-matchers (2.8.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
sidekiq (4.1.2) sidekiq (4.1.4)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0) connection_pool (~> 2.2, >= 2.2.0)
redis (~> 3.2, >= 3.2.1) redis (~> 3.2, >= 3.2.1)
sinatra (>= 1.4.7)
sidekiq-cron (0.4.0) sidekiq-cron (0.4.0)
redis-namespace (>= 1.5.2) redis-namespace (>= 1.5.2)
rufus-scheduler (>= 2.0.24) rufus-scheduler (>= 2.0.24)
...@@ -698,8 +699,8 @@ GEM ...@@ -698,8 +699,8 @@ GEM
json (~> 1.8) json (~> 1.8)
simplecov-html (~> 0.10.0) simplecov-html (~> 0.10.0)
simplecov-html (0.10.0) simplecov-html (0.10.0)
sinatra (1.4.6) sinatra (1.4.7)
rack (~> 1.4) rack (~> 1.5)
rack-protection (~> 1.4) rack-protection (~> 1.4)
tilt (>= 1.3, < 3) tilt (>= 1.3, < 3)
six (0.2.0) six (0.2.0)
...@@ -715,7 +716,7 @@ GEM ...@@ -715,7 +716,7 @@ GEM
spinach (>= 0.4) spinach (>= 0.4)
spinach-rerun-reporter (0.0.2) spinach-rerun-reporter (0.0.2)
spinach (~> 0.8) spinach (~> 0.8)
spring (1.7.1) spring (1.7.2)
spring-commands-rspec (1.0.4) spring-commands-rspec (1.0.4)
spring (>= 0.9.1) spring (>= 0.9.1)
spring-commands-spinach (1.1.0) spring-commands-spinach (1.1.0)
...@@ -749,10 +750,10 @@ GEM ...@@ -749,10 +750,10 @@ GEM
temple (0.7.7) temple (0.7.7)
test_after_commit (0.4.2) test_after_commit (0.4.2)
activerecord (>= 3.2) activerecord (>= 3.2)
thin (1.6.4) thin (1.7.0)
daemons (~> 1.0, >= 1.0.9) daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4) eventmachine (~> 1.0, >= 1.0.4)
rack (~> 1.0) rack (>= 1, < 3)
thor (0.19.1) thor (0.19.1)
thread_safe (0.3.5) thread_safe (0.3.5)
tilt (2.0.5) tilt (2.0.5)
...@@ -829,7 +830,7 @@ PLATFORMS ...@@ -829,7 +830,7 @@ PLATFORMS
ruby ruby
DEPENDENCIES DEPENDENCIES
RedCloth (~> 4.2.9) RedCloth (~> 4.3.2)
ace-rails-ap (~> 4.0.2) ace-rails-ap (~> 4.0.2)
activerecord-session_store (~> 1.0.0) activerecord-session_store (~> 1.0.0)
acts-as-taggable-on (~> 3.4) acts-as-taggable-on (~> 3.4)
...@@ -969,7 +970,7 @@ DEPENDENCIES ...@@ -969,7 +970,7 @@ DEPENDENCIES
responders (~> 2.0) responders (~> 2.0)
rouge (~> 1.11) rouge (~> 1.11)
rqrcode-rails3 (~> 0.1.7) rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.4.0) rspec-rails (~> 3.5.0)
rspec-retry rspec-retry
rubocop (~> 0.40.0) rubocop (~> 0.40.0)
rubocop-rspec (~> 1.5.0) rubocop-rspec (~> 1.5.0)
...@@ -1003,7 +1004,7 @@ DEPENDENCIES ...@@ -1003,7 +1004,7 @@ DEPENDENCIES
teaspoon (~> 1.1.0) teaspoon (~> 1.1.0)
teaspoon-jasmine (~> 2.2.0) teaspoon-jasmine (~> 2.2.0)
test_after_commit (~> 0.4.2) test_after_commit (~> 0.4.2)
thin (~> 1.6.1) thin (~> 1.7.0)
tinder (~> 1.10.0) tinder (~> 1.10.0)
turbolinks (~> 2.5.0) turbolinks (~> 2.5.0)
u2f (~> 0.2.1) u2f (~> 0.2.1)
......
...@@ -7,13 +7,16 @@ class @ImporterStatus ...@@ -7,13 +7,16 @@ class @ImporterStatus
$('.js-add-to-import') $('.js-add-to-import')
.off 'click' .off 'click'
.on 'click', (e) => .on 'click', (e) =>
new_namespace = null
$btn = $(e.currentTarget) $btn = $(e.currentTarget)
$tr = $btn.closest('tr') $tr = $btn.closest('tr')
$target_field = $tr.find('.import-target')
$namespace_input = $target_field.find('input')
id = $tr.attr('id').replace('repo_', '') id = $tr.attr('id').replace('repo_', '')
if $tr.find('.import-target input').length > 0 new_namespace = null
new_namespace = $tr.find('.import-target input').prop('value')
$tr.find('.import-target').empty().append("#{new_namespace} / #{$tr.find('.import-target').data('project_name')}") if $namespace_input.length > 0
new_namespace = $namespace_input.prop('value')
$target_field.empty().append("#{new_namespace}/#{$target_field.data('project_name')}")
$btn $btn
.disable() .disable()
......
...@@ -20,7 +20,8 @@ ...@@ -20,7 +20,8 @@
} }
.open { .open {
.dropdown-menu { .dropdown-menu,
.dropdown-menu-nav {
display: block; display: block;
} }
...@@ -66,7 +67,8 @@ ...@@ -66,7 +67,8 @@
} }
} }
.dropdown-menu { .dropdown-menu,
.dropdown-menu-nav {
display: none; display: none;
position: absolute; position: absolute;
top: 100%; top: 100%;
...@@ -77,7 +79,7 @@ ...@@ -77,7 +79,7 @@
margin-bottom: 0; margin-bottom: 0;
font-size: 15px; font-size: 15px;
font-weight: normal; font-weight: normal;
padding: 10px 0; padding: 8px 0;
background-color: $dropdown-bg; background-color: $dropdown-bg;
border: 1px solid $dropdown-border-color; border: 1px solid $dropdown-border-color;
border-radius: $border-radius-base; border-radius: $border-radius-base;
...@@ -101,12 +103,12 @@ ...@@ -101,12 +103,12 @@
li { li {
text-align: left; text-align: left;
list-style: none; list-style: none;
padding: 0 10px; padding: 0 8px;
} }
.divider { .divider {
height: 1px; height: 1px;
margin: 8px 10px; margin: 8px;
padding: 0; padding: 0;
background-color: $dropdown-divider-color; background-color: $dropdown-divider-color;
} }
...@@ -122,7 +124,7 @@ ...@@ -122,7 +124,7 @@
a { a {
display: block; display: block;
position: relative; position: relative;
padding: 5px 10px; padding: 5px 8px;
color: $dropdown-link-color; color: $dropdown-link-color;
line-height: initial; line-height: initial;
text-overflow: ellipsis; text-overflow: ellipsis;
......
...@@ -60,7 +60,7 @@ header { ...@@ -60,7 +60,7 @@ header {
margin: ($header-height - 28) / 2 0; margin: ($header-height - 28) / 2 0;
margin-left: 10px; margin-left: 10px;
height: 28px; height: 28px;
width: 28px; min-width: 28px;
line-height: 28px; line-height: 28px;
text-align: center; text-align: center;
...@@ -241,14 +241,23 @@ header { ...@@ -241,14 +241,23 @@ header {
.navbar-collapse { .navbar-collapse {
padding-left: 5px; padding-left: 5px;
li { .nav > li {
display: table-cell; display: table-cell;
width: 1%; width: 1%;
a {
margin-left: 8px !important;
}
} }
} }
} }
} }
.header-user {
.dropdown-menu-nav {
width: 140px;
margin-top: -5px;
}
}
.header-user-avatar {
float: left;
margin-right: 5px;
border-radius: 50%;
}
...@@ -10,6 +10,7 @@ class Admin::GroupsController < Admin::ApplicationController ...@@ -10,6 +10,7 @@ class Admin::GroupsController < Admin::ApplicationController
def show def show
@members = @group.members.order("access_level DESC").page(params[:members_page]) @members = @group.members.order("access_level DESC").page(params[:members_page])
@requesters = @group.requesters
@projects = @group.projects.page(params[:projects_page]) @projects = @group.projects.page(params[:projects_page])
end end
......
...@@ -22,7 +22,6 @@ class Admin::HooksController < Admin::ApplicationController ...@@ -22,7 +22,6 @@ class Admin::HooksController < Admin::ApplicationController
redirect_to admin_hooks_path redirect_to admin_hooks_path
end end
def test def test
@hook = SystemHook.find(params[:hook_id]) @hook = SystemHook.find(params[:hook_id])
data = { data = {
......
...@@ -20,7 +20,8 @@ class Admin::ProjectsController < Admin::ApplicationController ...@@ -20,7 +20,8 @@ class Admin::ProjectsController < Admin::ApplicationController
@group_members = @group.members.order("access_level DESC").page(params[:group_members_page]) @group_members = @group.members.order("access_level DESC").page(params[:group_members_page])
end end
@project_members = @project.project_members.page(params[:project_members_page]) @project_members = @project.members.page(params[:project_members_page])
@requesters = @project.requesters
end end
def transfer def transfer
......
...@@ -10,7 +10,7 @@ module MembershipActions ...@@ -10,7 +10,7 @@ module MembershipActions
end end
def approve_access_request def approve_access_request
@member = membershipable.members.request.find(params[:id]) @member = membershipable.requesters.find(params[:id])
return render_403 unless can?(current_user, action_member_permission(:update, @member), @member) return render_403 unless can?(current_user, action_member_permission(:update, @member), @member)
...@@ -22,7 +22,8 @@ module MembershipActions ...@@ -22,7 +22,8 @@ module MembershipActions
end end
def leave def leave
@member = membershipable.members.find_by(user_id: current_user) @member = membershipable.members.find_by(user_id: current_user) ||
membershipable.requesters.find_by(user_id: current_user)
Members::DestroyService.new(@member, current_user).execute Members::DestroyService.new(@member, current_user).execute
source_type = @member.real_source_type.humanize(capitalize: false) source_type = @member.real_source_type.humanize(capitalize: false)
......
class ConfirmationsController < Devise::ConfirmationsController class ConfirmationsController < Devise::ConfirmationsController
def almost_there def almost_there
flash[:notice] = nil flash[:notice] = nil
render layout: "devise_empty" render layout: "devise_empty"
......
...@@ -7,7 +7,7 @@ class Groups::GroupMembersController < Groups::ApplicationController ...@@ -7,7 +7,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
def index def index
@project = @group.projects.find(params[:project_id]) if params[:project_id] @project = @group.projects.find(params[:project_id]) if params[:project_id]
@members = @group.group_members @members = @group.group_members
@members = @members.non_pending unless can?(current_user, :admin_group, @group) @members = @members.non_invite unless can?(current_user, :admin_group, @group)
if params[:search].present? if params[:search].present?
users = @group.users.search(params[:search]).to_a users = @group.users.search(params[:search]).to_a
...@@ -15,6 +15,7 @@ class Groups::GroupMembersController < Groups::ApplicationController ...@@ -15,6 +15,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
end end
@members = @members.order('access_level DESC').page(params[:page]).per(50) @members = @members.order('access_level DESC').page(params[:page]).per(50)
@requesters = @group.requesters if can?(current_user, :admin_group, @group)
@group_member = @group.group_members.new @group_member = @group.group_members.new
end end
...@@ -46,7 +47,8 @@ class Groups::GroupMembersController < Groups::ApplicationController ...@@ -46,7 +47,8 @@ class Groups::GroupMembersController < Groups::ApplicationController
end end
def destroy def destroy
@group_member = @group.group_members.find(params[:id]) @group_member = @group.members.find_by(id: params[:id]) ||
@group.requesters.find_by(id: params[:id])
Members::DestroyService.new(@group_member, current_user).execute Members::DestroyService.new(@group_member, current_user).execute
log_audit_event(@group_member, action: :destroy) log_audit_event(@group_member, action: :destroy)
......
class Import::BaseController < ApplicationController class Import::BaseController < ApplicationController
private private
def get_or_create_namespace def get_or_create_namespace
......
...@@ -5,7 +5,6 @@ class Import::FogbugzController < Import::BaseController ...@@ -5,7 +5,6 @@ class Import::FogbugzController < Import::BaseController
rescue_from Fogbugz::AuthenticationException, with: :fogbugz_unauthorized rescue_from Fogbugz::AuthenticationException, with: :fogbugz_unauthorized
def new def new
end end
def callback def callback
...@@ -22,7 +21,6 @@ class Import::FogbugzController < Import::BaseController ...@@ -22,7 +21,6 @@ class Import::FogbugzController < Import::BaseController
end end
def new_user_map def new_user_map
end end
def create_user_map def create_user_map
......
...@@ -44,5 +44,4 @@ class Import::GitoriousController < Import::BaseController ...@@ -44,5 +44,4 @@ class Import::GitoriousController < Import::BaseController
def verify_gitorious_import_enabled def verify_gitorious_import_enabled
render_404 unless gitorious_import_enabled? render_404 unless gitorious_import_enabled?
end end
end end
...@@ -3,7 +3,6 @@ class Import::GoogleCodeController < Import::BaseController ...@@ -3,7 +3,6 @@ class Import::GoogleCodeController < Import::BaseController
before_action :user_map, only: [:new_user_map, :create_user_map] before_action :user_map, only: [:new_user_map, :create_user_map]
def new def new
end end
def callback def callback
...@@ -34,7 +33,6 @@ class Import::GoogleCodeController < Import::BaseController ...@@ -34,7 +33,6 @@ class Import::GoogleCodeController < Import::BaseController
end end
def new_user_map def new_user_map
end end
def create_user_map def create_user_map
......
...@@ -5,7 +5,6 @@ class InvitesController < ApplicationController ...@@ -5,7 +5,6 @@ class InvitesController < ApplicationController
respond_to :html respond_to :html
def show def show
end end
def accept def accept
......
...@@ -82,7 +82,6 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -82,7 +82,6 @@ class Projects::IssuesController < Projects::ApplicationController
render json: @issue.to_json(include: [:milestone, :labels]) render json: @issue.to_json(include: [:milestone, :labels])
end end
end end
end end
def create def create
......
...@@ -7,7 +7,6 @@ class Projects::NetworkController < Projects::ApplicationController ...@@ -7,7 +7,6 @@ class Projects::NetworkController < Projects::ApplicationController
before_action :authorize_download_code! before_action :authorize_download_code!
def show def show
@url = namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json)) @url = namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json))
@commit_url = namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s") @commit_url = namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s")
......
...@@ -6,7 +6,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -6,7 +6,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
def index def index
@project_members = @project.project_members @project_members = @project.project_members
@project_members = @project_members.non_pending unless can?(current_user, :admin_project, @project) @project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project)
if params[:search].present? if params[:search].present?
users = @project.users.search(params[:search]).to_a users = @project.users.search(params[:search]).to_a
...@@ -19,7 +19,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -19,7 +19,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
if @group if @group
@group_members = @group.group_members @group_members = @group.group_members
@group_members = @group_members.non_pending unless can?(current_user, :admin_group, @group) @group_members = @group_members.non_invite unless can?(current_user, :admin_group, @group)
if params[:search].present? if params[:search].present?
users = @group.users.search(params[:search]).to_a users = @group.users.search(params[:search]).to_a
...@@ -29,6 +29,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -29,6 +29,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController
@group_members = @group_members.order('access_level DESC') @group_members = @group_members.order('access_level DESC')
end end
@requesters = @project.requesters if can?(current_user, :admin_project, @project)
@project_member = @project.project_members.new @project_member = @project.project_members.new
@project_group_links = @project.project_group_links @project_group_links = @project.project_group_links
end end
...@@ -57,7 +59,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -57,7 +59,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController
end end
def destroy def destroy
@project_member = @project.project_members.find(params[:id]) @project_member = @project.members.find_by(id: params[:id]) ||
@project.requesters.find_by(id: params[:id])
Members::DestroyService.new(@project_member, current_user).execute Members::DestroyService.new(@project_member, current_user).execute
......
...@@ -54,7 +54,7 @@ class Projects::SnippetsController < Projects::ApplicationController ...@@ -54,7 +54,7 @@ class Projects::SnippetsController < Projects::ApplicationController
def show def show
@note = @project.notes.new(noteable: @snippet) @note = @project.notes.new(noteable: @snippet)
@notes = @snippet.notes.fresh @notes = Banzai::NoteRenderer.render(@snippet.notes.fresh, @project, current_user)
@noteable = @snippet @noteable = @snippet
end end
......
...@@ -133,5 +133,4 @@ class Projects::WikisController < Projects::ApplicationController ...@@ -133,5 +133,4 @@ class Projects::WikisController < Projects::ApplicationController
def wiki_params def wiki_params
params[:wiki].slice(:title, :content, :format, :message) params[:wiki].slice(:title, :content, :format, :message)
end end
end end
module EmailsHelper module EmailsHelper
# Google Actions # Google Actions
# https://developers.google.com/gmail/markup/reference/go-to-action # https://developers.google.com/gmail/markup/reference/go-to-action
def email_action(url) def email_action(url)
......
module IssuablesHelper module IssuablesHelper
def sidebar_gutter_toggle_icon def sidebar_gutter_toggle_icon
sidebar_gutter_collapsed? ? icon('angle-double-left') : icon('angle-double-right') sidebar_gutter_collapsed? ? icon('angle-double-left') : icon('angle-double-right')
end end
......
...@@ -12,6 +12,17 @@ module MembersHelper ...@@ -12,6 +12,17 @@ module MembersHelper
can?(current_user, action_member_permission(:admin, member), member.source) can?(current_user, action_member_permission(:admin, member), member.source)
end end
def can_see_request_access_button?(source)
source_parent = source.respond_to?(:group) && source.group
return false if source_parent && source.group.members.exists?(user_id: current_user.id)
return false if source_parent && source.group.requesters.exists?(user_id: current_user.id)
return false if source.members.exists?(user_id: current_user.id)
return true if source.requesters.exists?(user_id: current_user.id)
true
end
def remove_member_message(member, user: nil) def remove_member_message(member, user: nil)
user = current_user if defined?(current_user) user = current_user if defined?(current_user)
......
module SearchHelper module SearchHelper
def search_autocomplete_opts(term) def search_autocomplete_opts(term)
return unless current_user return unless current_user
......
...@@ -19,6 +19,7 @@ module Ci ...@@ -19,6 +19,7 @@ module Ci
acts_as_taggable acts_as_taggable
before_save :update_artifacts_size, if: :artifacts_file_changed?
before_destroy { project } before_destroy { project }
after_create :execute_hooks after_create :execute_hooks
...@@ -330,7 +331,12 @@ module Ci ...@@ -330,7 +331,12 @@ module Ci
end end
def artifacts_metadata_entry(path, **options) def artifacts_metadata_entry(path, **options)
Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path, **options).to_entry metadata = Gitlab::Ci::Build::Artifacts::Metadata.new(
artifacts_metadata.path,
path,
**options)
metadata.to_entry
end end
def erase_artifacts! def erase_artifacts!
...@@ -376,6 +382,14 @@ module Ci ...@@ -376,6 +382,14 @@ module Ci
private private
def update_artifacts_size
self.artifacts_size = if artifacts_file.exists?
artifacts_file.size
else
nil
end
end
def erase_trace! def erase_trace!
self.trace = nil self.trace = nil
end end
......
...@@ -16,6 +16,7 @@ module Ci ...@@ -16,6 +16,7 @@ module Ci
# Invalidate object and save if when touched # Invalidate object and save if when touched
after_touch :update_state after_touch :update_state
after_save :keep_around_commits
def self.truncate_sha(sha) def self.truncate_sha(sha)
sha[0...8] sha[0...8]
...@@ -212,5 +213,10 @@ module Ci ...@@ -212,5 +213,10 @@ module Ci
self.duration = statuses.latest.duration self.duration = statuses.latest.duration
save save
end end
def keep_around_commits
project.repository.keep_around(self.sha)
project.repository.keep_around(self.before_sha)
end
end end
end end
module Ci module Ci
class TriggerRequest < ActiveRecord::Base class TriggerRequest < ActiveRecord::Base
extend Ci::Model extend Ci::Model
belongs_to :trigger, class_name: 'Ci::Trigger' belongs_to :trigger, class_name: 'Ci::Trigger'
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
has_many :builds, class_name: 'Ci::Build' has_many :builds, class_name: 'Ci::Build'
......
...@@ -61,7 +61,6 @@ module Issuable ...@@ -61,7 +61,6 @@ module Issuable
scope :references_project, -> { references(:project) } scope :references_project, -> { references(:project) }
scope :non_archived, -> { join_project.where(projects: { archived: false }) } scope :non_archived, -> { join_project.where(projects: { archived: false }) }
delegate :name, delegate :name,
:email, :email,
to: :author, to: :author,
......
...@@ -45,7 +45,7 @@ module Mentionable ...@@ -45,7 +45,7 @@ module Mentionable
def all_references(current_user = nil, text = nil, extractor: nil) def all_references(current_user = nil, text = nil, extractor: nil)
extractor ||= Gitlab::ReferenceExtractor. extractor ||= Gitlab::ReferenceExtractor.
new(project, current_user || author) new(project, current_user)
if text if text
extractor.analyze(text, author: author) extractor.analyze(text, author: author)
......
...@@ -6,15 +6,16 @@ class Group < Namespace ...@@ -6,15 +6,16 @@ class Group < Namespace
include AccessRequestable include AccessRequestable
include Referable include Referable
has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember'
alias_method :members, :group_members alias_method :members, :group_members
has_many :users, -> { where(members: { requested_at: nil }) }, through: :group_members has_many :users, through: :group_members
has_many :owners, has_many :owners,
-> { where(members: { requested_at: nil, access_level: Gitlab::Access::OWNER }) }, -> { where(members: { access_level: Gitlab::Access::OWNER }) },
through: :group_members, through: :group_members,
source: :user source: :user
has_many :requesters, -> { where.not(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember'
has_many :project_group_links, dependent: :destroy has_many :project_group_links, dependent: :destroy
has_many :shared_projects, through: :project_group_links, source: :project has_many :shared_projects, through: :project_group_links, source: :project
has_many :ldap_group_links, foreign_key: 'group_id', dependent: :destroy has_many :ldap_group_links, foreign_key: 'group_id', dependent: :destroy
......
...@@ -31,8 +31,6 @@ class Member < ActiveRecord::Base ...@@ -31,8 +31,6 @@ class Member < ActiveRecord::Base
scope :invite, -> { where.not(invite_token: nil) } scope :invite, -> { where.not(invite_token: nil) }
scope :non_invite, -> { where(invite_token: nil) } scope :non_invite, -> { where(invite_token: nil) }
scope :request, -> { where.not(requested_at: nil) } scope :request, -> { where.not(requested_at: nil) }
scope :non_request, -> { where(requested_at: nil) }
scope :non_pending, -> { non_request.non_invite }
scope :has_access, -> { where('access_level > 0') } scope :has_access, -> { where('access_level > 0') }
scope :guests, -> { where(access_level: GUEST) } scope :guests, -> { where(access_level: GUEST) }
......
...@@ -15,7 +15,6 @@ class ProjectMember < Member ...@@ -15,7 +15,6 @@ class ProjectMember < Member
before_destroy :delete_member_todos before_destroy :delete_member_todos
class << self class << self
# Add users to project teams with passed access option # Add users to project teams with passed access option
# #
# access can be an integer representing a access code # access can be an integer representing a access code
......
...@@ -121,6 +121,8 @@ class MergeRequest < ActiveRecord::Base ...@@ -121,6 +121,8 @@ class MergeRequest < ActiveRecord::Base
scope :references_project, -> { references(:target_project) } scope :references_project, -> { references(:target_project) }
participant :approvers_left participant :approvers_left
after_save :keep_around_commit
def self.reference_prefix def self.reference_prefix
'!' '!'
...@@ -609,12 +611,12 @@ class MergeRequest < ActiveRecord::Base ...@@ -609,12 +611,12 @@ class MergeRequest < ActiveRecord::Base
"refs/merge-requests/#{iid}/head" "refs/merge-requests/#{iid}/head"
end end
def ref_is_fetched? def ref_fetched?
File.exist?(File.join(project.repository.path_to_repo, ref_path)) project.repository.ref_exists?(ref_path)
end end
def ensure_ref_fetched def ensure_ref_fetched
fetch_ref unless ref_is_fetched? fetch_ref unless ref_fetched?
end end
def in_locked_state def in_locked_state
...@@ -693,4 +695,8 @@ class MergeRequest < ActiveRecord::Base ...@@ -693,4 +695,8 @@ class MergeRequest < ActiveRecord::Base
def can_be_cherry_picked? def can_be_cherry_picked?
merge_commit merge_commit
end end
def keep_around_commit
project.repository.keep_around(self.merge_commit_sha)
end
end end
...@@ -24,6 +24,7 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -24,6 +24,7 @@ class MergeRequestDiff < ActiveRecord::Base
serialize :st_diffs serialize :st_diffs
after_create :reload_content, unless: :importing? after_create :reload_content, unless: :importing?
after_save :keep_around_commit
def reload_content def reload_content
reload_commits reload_commits
...@@ -145,7 +146,11 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -145,7 +146,11 @@ class MergeRequestDiff < ActiveRecord::Base
end end
new_attributes[:st_diffs] = new_diffs new_attributes[:st_diffs] = new_diffs
new_attributes[:base_commit_sha] = self.repository.merge_base(self.head, self.base)
base_commit_sha = self.repository.merge_base(self.head, self.base)
new_attributes[:base_commit_sha] = base_commit_sha
self.repository.keep_around(base_commit_sha)
update_columns_serialized(new_attributes) update_columns_serialized(new_attributes)
end end
...@@ -217,4 +222,8 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -217,4 +222,8 @@ class MergeRequestDiff < ActiveRecord::Base
update_columns(new_attributes.merge(updated_at: current_time_from_proper_timezone)) update_columns(new_attributes.merge(updated_at: current_time_from_proper_timezone))
reload reload
end end
def keep_around_commit
self.repository.keep_around(self.base_commit_sha)
end
end end
...@@ -68,6 +68,7 @@ class Note < ActiveRecord::Base ...@@ -68,6 +68,7 @@ class Note < ActiveRecord::Base
end end
before_validation :clear_blank_line_code! before_validation :clear_blank_line_code!
after_save :keep_around_commit
class << self class << self
def model_name def model_name
...@@ -221,4 +222,10 @@ class Note < ActiveRecord::Base ...@@ -221,4 +222,10 @@ class Note < ActiveRecord::Base
original_name = note.match(Banzai::Filter::EmojiFilter.emoji_pattern)[1] original_name = note.match(Banzai::Filter::EmojiFilter.emoji_pattern)[1]
Gitlab::AwardEmoji.normalize_emoji_name(original_name) Gitlab::AwardEmoji.normalize_emoji_name(original_name)
end end
private
def keep_around_commit
project.repository.keep_around(self.commit_id)
end
end end
...@@ -107,9 +107,13 @@ class Project < ActiveRecord::Base ...@@ -107,9 +107,13 @@ class Project < ActiveRecord::Base
has_many :snippets, dependent: :destroy, class_name: 'ProjectSnippet' has_many :snippets, dependent: :destroy, class_name: 'ProjectSnippet'
has_many :hooks, dependent: :destroy, class_name: 'ProjectHook' has_many :hooks, dependent: :destroy, class_name: 'ProjectHook'
has_many :protected_branches, dependent: :destroy has_many :protected_branches, dependent: :destroy
has_many :project_members, dependent: :destroy, as: :source, class_name: 'ProjectMember'
has_many :project_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'ProjectMember'
alias_method :members, :project_members alias_method :members, :project_members
has_many :users, -> { where(members: { requested_at: nil }) }, through: :project_members has_many :users, through: :project_members
has_many :requesters, -> { where.not(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'ProjectMember'
has_many :deploy_keys_projects, dependent: :destroy has_many :deploy_keys_projects, dependent: :destroy
has_many :deploy_keys, through: :deploy_keys_projects has_many :deploy_keys, through: :deploy_keys_projects
has_many :users_star_projects, dependent: :destroy has_many :users_star_projects, dependent: :destroy
......
class BugzillaService < IssueTrackerService class BugzillaService < IssueTrackerService
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
def title def title
...@@ -21,5 +20,4 @@ class BugzillaService < IssueTrackerService ...@@ -21,5 +20,4 @@ class BugzillaService < IssueTrackerService
def to_param def to_param
'bugzilla' 'bugzilla'
end end
end end
class CustomIssueTrackerService < IssueTrackerService class CustomIssueTrackerService < IssueTrackerService
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
def title def title
...@@ -31,5 +30,4 @@ class CustomIssueTrackerService < IssueTrackerService ...@@ -31,5 +30,4 @@ class CustomIssueTrackerService < IssueTrackerService
{ type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' } { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' }
] ]
end end
end end
class DroneCiService < CiService class DroneCiService < CiService
prop_accessor :drone_url, :token, :enable_ssl_verification prop_accessor :drone_url, :token, :enable_ssl_verification
validates :drone_url, presence: true, url: true, if: :activated? validates :drone_url, presence: true, url: true, if: :activated?
......
class IssueTrackerService < Service class IssueTrackerService < Service
validates :project_url, :issues_url, :new_issue_url, presence: true, url: true, if: :activated? validates :project_url, :issues_url, :new_issue_url, presence: true, url: true, if: :activated?
default_value_for :category, 'issue_tracker' default_value_for :category, 'issue_tracker'
......
...@@ -190,7 +190,6 @@ class JiraService < IssueTrackerService ...@@ -190,7 +190,6 @@ class JiraService < IssueTrackerService
end end
end end
def auth def auth
require 'base64' require 'base64'
Base64.urlsafe_encode64("#{self.username}:#{self.password}") Base64.urlsafe_encode64("#{self.username}:#{self.password}")
......
class RedmineService < IssueTrackerService class RedmineService < IssueTrackerService
prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
def title def title
......
...@@ -22,12 +22,12 @@ class ProjectTeam ...@@ -22,12 +22,12 @@ class ProjectTeam
end end
def find_member(user_id) def find_member(user_id)
member = project.members.non_request.find_by(user_id: user_id) member = project.members.find_by(user_id: user_id)
# If user is not in project members # If user is not in project members
# we should check for group membership # we should check for group membership
if group && !member if group && !member
member = group.members.non_request.find_by(user_id: user_id) member = group.members.find_by(user_id: user_id)
end end
member member
...@@ -139,10 +139,10 @@ class ProjectTeam ...@@ -139,10 +139,10 @@ class ProjectTeam
def max_member_access(user_id) def max_member_access(user_id)
access = [] access = []
access += project.members.non_request.where(user_id: user_id).has_access.pluck(:access_level) access += project.members.where(user_id: user_id).has_access.pluck(:access_level)
if group if group
access += group.members.non_request.where(user_id: user_id).has_access.pluck(:access_level) access += group.members.where(user_id: user_id).has_access.pluck(:access_level)
end end
if project.invited_groups.any? && project.allowed_to_share_with_group? if project.invited_groups.any? && project.allowed_to_share_with_group?
...@@ -170,14 +170,14 @@ class ProjectTeam ...@@ -170,14 +170,14 @@ class ProjectTeam
end end
def fetch_members(level = nil) def fetch_members(level = nil)
project_members = project.members.non_request project_members = project.members
group_members = group ? group.members.non_request : [] group_members = group ? group.members : []
invited_members = [] invited_members = []
if project.invited_groups.any? && project.allowed_to_share_with_group? if project.invited_groups.any? && project.allowed_to_share_with_group?
project.project_group_links.each do |group_link| project.project_group_links.each do |group_link|
invited_group = group_link.group invited_group = group_link.group
im = invited_group.members.non_request im = invited_group.members
if level if level
int_level = GroupMember.access_level_roles[level.to_s.singularize.titleize] int_level = GroupMember.access_level_roles[level.to_s.singularize.titleize]
......
...@@ -255,6 +255,26 @@ class Repository ...@@ -255,6 +255,26 @@ class Repository
branch_names.include?(branch_name) branch_names.include?(branch_name)
end end
def ref_exists?(ref)
rugged.references.exist?(ref)
end
# Makes sure a commit is kept around when Git garbage collection runs.
# Git GC will delete commits from the repository that are no longer in any
# branches or tags, but we want to keep some of these commits around, for
# example if they have comments or CI builds.
def keep_around(sha)
return unless sha && commit(sha)
return if kept_around?(sha)
rugged.references.create(keep_around_ref_name(sha), sha)
end
def kept_around?(sha)
ref_exists?(keep_around_ref_name(sha))
end
def tag_names def tag_names
cache.fetch(:tag_names) { raw_repository.tag_names } cache.fetch(:tag_names) { raw_repository.tag_names }
end end
...@@ -1003,7 +1023,6 @@ class Repository ...@@ -1003,7 +1023,6 @@ class Repository
merge_base(ancestor_id, descendant_id) == ancestor_id merge_base(ancestor_id, descendant_id) == ancestor_id
end end
def search_files(query, ref) def search_files(query, ref)
offset = 2 offset = 2
args = %W(#{Gitlab.config.git.bin_path} grep -i -I -n --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref}) args = %W(#{Gitlab.config.git.bin_path} grep -i -I -n --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref})
...@@ -1204,4 +1223,8 @@ class Repository ...@@ -1204,4 +1223,8 @@ class Repository
def tags_sorted_by_committed_date def tags_sorted_by_committed_date
tags.sort_by { |tag| commit(tag.target).committed_date } tags.sort_by { |tag| commit(tag.target).committed_date }
end end
def keep_around_ref_name(sha)
"refs/keep-around/#{sha}"
end
end end
...@@ -9,6 +9,8 @@ class SentNotification < ActiveRecord::Base ...@@ -9,6 +9,8 @@ class SentNotification < ActiveRecord::Base
validates :commit_id, presence: true, if: :for_commit? validates :commit_id, presence: true, if: :for_commit?
validates :line_code, line_code: true, allow_blank: true validates :line_code, line_code: true, allow_blank: true
after_save :keep_around_commit
class << self class << self
def reply_key def reply_key
SecureRandom.hex(16) SecureRandom.hex(16)
...@@ -67,4 +69,10 @@ class SentNotification < ActiveRecord::Base ...@@ -67,4 +69,10 @@ class SentNotification < ActiveRecord::Base
def to_param def to_param
self.reply_key self.reply_key
end end
private
def keep_around_commit
project.repository.keep_around(self.commit_id)
end
end end
...@@ -37,6 +37,8 @@ class Todo < ActiveRecord::Base ...@@ -37,6 +37,8 @@ class Todo < ActiveRecord::Base
state :done state :done
end end
after_save :keep_around_commit
def build_failed? def build_failed?
action == BUILD_FAILED action == BUILD_FAILED
end end
...@@ -73,4 +75,10 @@ class Todo < ActiveRecord::Base ...@@ -73,4 +75,10 @@ class Todo < ActiveRecord::Base
target.to_reference target.to_reference
end end
end end
private
def keep_around_commit
project.repository.keep_around(self.commit_id)
end
end end
...@@ -889,7 +889,6 @@ class User < ActiveRecord::Base ...@@ -889,7 +889,6 @@ class User < ActiveRecord::Base
projects.select(:id), projects.select(:id),
groups.joins(:shared_projects).select(:project_id)] groups.joins(:shared_projects).select(:project_id)]
if min_access_level if min_access_level
scope = { access_level: Gitlab::Access.values.select { |access| access >= min_access_level } } scope = { access_level: Gitlab::Access.values.select { |access| access >= min_access_level } }
relations = [relations.shift] + relations.map { |relation| relation.where(members: scope) } relations = [relations.shift] + relations.map { |relation| relation.where(members: scope) }
......
...@@ -34,8 +34,8 @@ class CreateBranchService < BaseService ...@@ -34,8 +34,8 @@ class CreateBranchService < BaseService
else else
error('Invalid reference name') error('Invalid reference name')
end end
rescue GitHooksService::PreReceiveError rescue GitHooksService::PreReceiveError => ex
error('Branch creation was rejected by Git hook') error(ex.message)
end end
def success(branch) def success(branch)
......
...@@ -2,7 +2,6 @@ require_relative 'base_service' ...@@ -2,7 +2,6 @@ require_relative 'base_service'
class CreateReleaseService < BaseService class CreateReleaseService < BaseService
def execute(tag_name, release_description) def execute(tag_name, release_description)
repository = project.repository repository = project.repository
existing_tag = repository.find_tag(tag_name) existing_tag = repository.find_tag(tag_name)
......
...@@ -13,8 +13,8 @@ class CreateTagService < BaseService ...@@ -13,8 +13,8 @@ class CreateTagService < BaseService
new_tag = repository.add_tag(current_user, tag_name, target, message) new_tag = repository.add_tag(current_user, tag_name, target, message)
rescue Rugged::TagError rescue Rugged::TagError
return error("Tag #{tag_name} already exists") return error("Tag #{tag_name} already exists")
rescue GitHooksService::PreReceiveError rescue GitHooksService::PreReceiveError => ex
return error('Tag creation was rejected by Git hook') return error(ex.message)
end end
if new_tag if new_tag
......
...@@ -30,8 +30,8 @@ class DeleteBranchService < BaseService ...@@ -30,8 +30,8 @@ class DeleteBranchService < BaseService
else else
error('Failed to remove branch') error('Failed to remove branch')
end end
rescue GitHooksService::PreReceiveError rescue GitHooksService::PreReceiveError => ex
error('Branch deletion was rejected by Git hook') error(ex.message)
end end
def error(message, return_code = 400) def error(message, return_code = 400)
......
...@@ -9,8 +9,10 @@ class GitHooksService ...@@ -9,8 +9,10 @@ class GitHooksService
@ref = ref @ref = ref
%w(pre-receive update).each do |hook_name| %w(pre-receive update).each do |hook_name|
unless run_hook(hook_name) status, message = run_hook(hook_name)
raise PreReceiveError.new("Git operation was rejected by #{hook_name} hook")
unless status
raise PreReceiveError, message
end end
end end
......
module Issues module Issues
class BaseService < ::IssuableBaseService class BaseService < ::IssuableBaseService
def hook_data(issue, action) def hook_data(issue, action)
issue_data = issue.to_hook_data(current_user) issue_data = issue.to_hook_data(current_user)
issue_url = Gitlab::UrlBuilder.build(issue) issue_url = Gitlab::UrlBuilder.build(issue)
......
module MergeRequests module MergeRequests
class BaseService < ::IssuableBaseService class BaseService < ::IssuableBaseService
def create_note(merge_request) def create_note(merge_request)
SystemNoteService.change_status(merge_request, merge_request.target_project, current_user, merge_request.state, nil) SystemNoteService.change_status(merge_request, merge_request.target_project, current_user, merge_request.state, nil)
end end
......
...@@ -60,10 +60,13 @@ module MergeRequests ...@@ -60,10 +60,13 @@ module MergeRequests
commit_id = repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options) commit_id = repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options)
merge_request.update(merge_commit_sha: commit_id) merge_request.update(merge_commit_sha: commit_id)
rescue GitHooksService::PreReceiveError => e
merge_request.update(merge_error: e.message)
false
rescue StandardError => e rescue StandardError => e
merge_request.update(merge_error: "Something went wrong during merge") merge_request.update(merge_error: "Something went wrong during merge")
Rails.logger.error(e.message) Rails.logger.error(e.message)
return false false
end end
def after_merge def after_merge
......
...@@ -40,6 +40,5 @@ module MergeRequests ...@@ -40,6 +40,5 @@ module MergeRequests
error("Can't cancel the automatic merge", 406) error("Can't cancel the automatic merge", 406)
end end
end end
end end
end end
module Milestones module Milestones
class DestroyService < Milestones::BaseService class DestroyService < Milestones::BaseService
def execute(milestone) def execute(milestone)
Milestone.transaction do Milestone.transaction do
update_params = { milestone: nil } update_params = { milestone: nil }
......
module Projects module Projects
class DownloadService < BaseService class DownloadService < BaseService
WHITELIST = [ WHITELIST = [
/^[^.]+\.fogbugz.com$/ /^[^.]+\.fogbugz.com$/
] ]
......
module Projects module Projects
module ImportExport module ImportExport
class ExportService < BaseService class ExportService < BaseService
def execute(_options = {}) def execute(_options = {})
@shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work')) @shared = Gitlab::ImportExport::Shared.new(relative_path: File.join(project.path_with_namespace, 'work'))
save_all save_all
......
...@@ -293,7 +293,6 @@ class SystemNoteService ...@@ -293,7 +293,6 @@ class SystemNoteService
end end
end end
def self.cross_reference?(note_text) def self.cross_reference?(note_text)
note_text.start_with?(cross_reference_note_prefix) note_text.start_with?(cross_reference_note_prefix)
end end
......
...@@ -237,7 +237,7 @@ class TodoService ...@@ -237,7 +237,7 @@ class TodoService
end end
def filter_mentioned_users(project, target, author) def filter_mentioned_users(project, target, author)
mentioned_users = target.mentioned_users mentioned_users = target.mentioned_users(author)
mentioned_users = reject_users_without_access(mentioned_users, project, target) mentioned_users = reject_users_without_access(mentioned_users, project, target)
mentioned_users.delete(author) mentioned_users.delete(author)
mentioned_users.uniq mentioned_users.uniq
......
...@@ -2,7 +2,6 @@ require_relative 'base_service' ...@@ -2,7 +2,6 @@ require_relative 'base_service'
class UpdateReleaseService < BaseService class UpdateReleaseService < BaseService
def execute(tag_name, release_description) def execute(tag_name, release_description)
repository = project.repository repository = project.repository
existing_tag = repository.find_tag(tag_name) existing_tag = repository.find_tag(tag_name)
......
module WikiPages module WikiPages
class BaseService < ::BaseService class BaseService < ::BaseService
def hook_data(page, action) def hook_data(page, action)
hook_data = { hook_data = {
object_kind: page.class.name.underscore, object_kind: page.class.name.underscore,
......
...@@ -100,16 +100,16 @@ ...@@ -100,16 +100,16 @@
%hr %hr
= button_tag 'Add users to group', class: "btn btn-create" = button_tag 'Add users to group', class: "btn btn-create"
= render 'shared/members/requests', membership_source: @group, members: @members.request = render 'shared/members/requests', membership_source: @group, requesters: @requesters
.panel.panel-default .panel.panel-default
.panel-heading .panel-heading
%strong= @group.name %strong= @group.name
group members group members
%span.badge= @group.members.non_request.size %span.badge= @group.members.size
.pull-right .pull-right
= link_to icon('pencil-square-o', text: 'Manage Access'), polymorphic_url([@group, :members]), class: "btn btn-xs" = link_to icon('pencil-square-o', text: 'Manage Access'), polymorphic_url([@group, :members]), class: "btn btn-xs"
%ul.well-list.group-users-list.content-list %ul.well-list.group-users-list.content-list
= render partial: 'shared/members/member', collection: @members.non_request, as: :member, locals: { show_controls: false } = render partial: 'shared/members/member', collection: @members, as: :member, locals: { show_controls: false }
.panel-footer .panel-footer
= paginate @members.non_request, param_name: 'members_page', theme: 'gitlab' = paginate @members, param_name: 'members_page', theme: 'gitlab'
...@@ -137,16 +137,16 @@ ...@@ -137,16 +137,16 @@
.panel-heading .panel-heading
%strong= @group.name %strong= @group.name
group members group members
%span.badge= @group_members.non_request.size %span.badge= @group_members.size
.pull-right .pull-right
= link_to admin_group_path(@group), class: 'btn btn-xs' do = link_to admin_group_path(@group), class: 'btn btn-xs' do
= icon('pencil-square-o', text: 'Manage Access') = icon('pencil-square-o', text: 'Manage Access')
%ul.well-list.content-list %ul.well-list.content-list
= render partial: 'shared/members/member', collection: @group_members.non_request, as: :member, locals: { show_controls: false } = render partial: 'shared/members/member', collection: @group_members, as: :member, locals: { show_controls: false }
.panel-footer .panel-footer
= paginate @group_members.non_request, param_name: 'group_members_page', theme: 'gitlab' = paginate @group_members, param_name: 'group_members_page', theme: 'gitlab'
= render 'shared/members/requests', membership_source: @project, members: @project_members.request = render 'shared/members/requests', membership_source: @project, requesters: @requesters
.panel.panel-default .panel.panel-default
.panel-heading .panel-heading
...@@ -156,6 +156,6 @@ ...@@ -156,6 +156,6 @@
.pull-right .pull-right
= link_to icon('pencil-square-o', text: 'Manage Access'), polymorphic_url([@project, :members]), class: "btn btn-xs" = link_to icon('pencil-square-o', text: 'Manage Access'), polymorphic_url([@project, :members]), class: "btn btn-xs"
%ul.well-list.project_members.content-list %ul.well-list.project_members.content-list
= render partial: 'shared/members/member', collection: @project_members.non_request, as: :member, locals: { show_controls: false } = render partial: 'shared/members/member', collection: @project_members, as: :member, locals: { show_controls: false }
.panel-footer .panel-footer
= paginate @project_members.non_request, param_name: 'project_members_page', theme: 'gitlab' = paginate @project_members, param_name: 'project_members_page', theme: 'gitlab'
- page_title "Members" - page_title "Members"
.group-members-page.prepend-top-default .group-members-page.prepend-top-default
<<<<<<< HEAD
- if current_user && can?(current_user, :admin_group_member, @group) - if current_user && can?(current_user, :admin_group_member, @group)
=======
- if can?(current_user, :admin_group_member, @group)
>>>>>>> 06c7d6f3a863a1ac8d9f47fed8423387d6e672a6
.panel.panel-default .panel.panel-default
.panel-heading .panel-heading
Add new user to group Add new user to group
...@@ -11,6 +15,7 @@ ...@@ -11,6 +15,7 @@
.new-group-member-holder .new-group-member-holder
= render "new_group_member" = render "new_group_member"
<<<<<<< HEAD
- if current_user && @group.ldap_synced? - if current_user && @group.ldap_synced?
.bs-callout.bs-callout-info .bs-callout.bs-callout-info
The members of this group are managed using LDAP and cannot be added, changed or removed here. The members of this group are managed using LDAP and cannot be added, changed or removed here.
...@@ -32,12 +37,15 @@ ...@@ -32,12 +37,15 @@
- if current_user && can?(current_user, :admin_group_member, @group) - if current_user && can?(current_user, :admin_group_member, @group)
= render 'shared/members/requests', membership_source: @group, members: @members.request = render 'shared/members/requests', membership_source: @group, members: @members.request
=======
= render 'shared/members/requests', membership_source: @group, requesters: @requesters
>>>>>>> 06c7d6f3a863a1ac8d9f47fed8423387d6e672a6
.panel.panel-default .panel.panel-default
.panel-heading .panel-heading
%strong #{@group.name} %strong #{@group.name}
group members group members
%span.badge= @members.non_request.size %span.badge= @members.size
.controls .controls
= form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do
.form-group .form-group
...@@ -45,8 +53,8 @@ ...@@ -45,8 +53,8 @@
= button_tag class: 'btn', title: 'Search' do = button_tag class: 'btn', title: 'Search' do
= icon("search") = icon("search")
%ul.content-list %ul.content-list
= render partial: 'shared/members/member', collection: @members.non_request, as: :member = render partial: 'shared/members/member', collection: @members, as: :member
= paginate @members.non_request, theme: 'gitlab' = paginate @members, theme: 'gitlab'
:javascript :javascript
$('form.member-search-form').on('submit', function(event) { $('form.member-search-form').on('submit', function(event) {
......
- if @already_been_taken - if @already_been_taken
:plain :plain
target_field = $("tr#repo_#{@repo_id} .import-target") tr = $("tr#repo_#{@repo_id}")
target_field = tr.find(".import-target")
import_button = tr.find(".btn-import")
origin_target = target_field.text() origin_target = target_field.text()
project_name = "#{@project_name}" project_name = "#{@project_name}"
origin_namespace = "#{@target_namespace}" origin_namespace = "#{@target_namespace}"
...@@ -10,6 +12,7 @@ ...@@ -10,6 +12,7 @@
target_field.append("/" + project_name) target_field.append("/" + project_name)
target_field.data("project_name", project_name) target_field.data("project_name", project_name)
target_field.find('input').prop("value", origin_namespace) target_field.find('input').prop("value", origin_namespace)
import_button.enable().removeClass('is-loading')
- elsif @access_denied - elsif @access_denied
:plain :plain
job = $("tr#repo_#{@repo_id}") job = $("tr#repo_#{@repo_id}")
......
...@@ -42,9 +42,17 @@ ...@@ -42,9 +42,17 @@
= link_to sherlock_transactions_path, title: 'Sherlock Transactions', = link_to sherlock_transactions_path, title: 'Sherlock Transactions',
data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('tachometer fw') = icon('tachometer fw')
%li %li.header-user.dropdown
= link_to destroy_user_session_path, class: 'logout', method: :delete, title: 'Sign out', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = link_to current_user, class: "header-user-dropdown-toggle", data: { toggle: "dropdown" } do
= icon('sign-out') = image_tag avatar_icon(current_user, 26), width: 26, height: 26, class: "header-user-avatar"
%span.caret
.dropdown-menu-nav.dropdown-menu-align-right
%ul
%li
= link_to "Profile", current_user
%li.divider
%li
= link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link", title: 'Sign out'
- else - else
%li %li
%div %div
......
- if current_user - if current_user
- can_edit = can?(current_user, :admin_group, @group) - can_edit = can?(current_user, :admin_group, @group)
- member = @group.members.non_request.find_by(user_id: current_user.id) - member = @group.members.find_by(user_id: current_user.id)
- can_leave = member && can?(current_user, :destroy_group_member, member) - can_leave = member && can?(current_user, :destroy_group_member, member)
.controls .controls
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
%ul.dropdown-menu.dropdown-menu-align-right %ul.dropdown-menu.dropdown-menu-align-right
- can_edit = can?(current_user, :admin_project, @project) - can_edit = can?(current_user, :admin_project, @project)
-# We don't use @project.team.find_member because it searches for group members too... -# We don't use @project.team.find_member because it searches for group members too...
- member = @project.members.non_request.find_by(user_id: current_user.id) - member = @project.members.find_by(user_id: current_user.id)
- can_leave = member && can?(current_user, :destroy_project_member, member) - can_leave = member && can?(current_user, :destroy_project_member, member)
= render 'layouts/nav/project_settings', can_edit: can_edit = render 'layouts/nav/project_settings', can_edit: can_edit
......
- @project_group_links.each do |group_links| - @project_group_links.each do |group_links|
- shared_group = group_links.group - shared_group = group_links.group
- shared_group_members = shared_group.members.non_request - shared_group_members = shared_group.members
- shared_group_users_count = shared_group_members.size - shared_group_users_count = shared_group_members.size
.panel.panel-default .panel.panel-default
.panel-heading .panel-heading
......
...@@ -17,12 +17,12 @@ ...@@ -17,12 +17,12 @@
Users with access to this project are listed below. Users with access to this project are listed below.
= render "new_project_member" = render "new_project_member"
= render 'shared/members/requests', membership_source: @project, members: @project_members.request = render 'shared/members/requests', membership_source: @project, requesters: @requesters
= render 'team', members: @project_members.non_request = render 'team', members: @project_members
- if @group - if @group
= render "group_members", members: @group_members.non_request = render "group_members", members: @group_members
- if @project_group_links.any? && @project.allowed_to_share_with_group? - if @project_group_links.any? && @project.allowed_to_share_with_group?
= render "shared_group_members" = render "shared_group_members"
- member = source.members.find_by(user_id: current_user.id) - if can_see_request_access_button?(source)
- group_member = source.group.members.find_by(user_id: current_user.id) if source.respond_to?(:group) && source.group - if requester = source.requesters.find_by(user_id: current_user.id)
= link_to 'Withdraw Access Request', polymorphic_path([:leave, source, :members]),
- unless group_member method: :delete,
- if member data: { confirm: remove_member_message(requester) },
- if member.request? class: 'btn'
= link_to 'Withdraw Access Request', polymorphic_path([:leave, source, :members]),
method: :delete,
data: { confirm: remove_member_message(member) },
class: 'btn'
- else - else
= link_to 'Request Access', polymorphic_path([:request_access, source, :members]), = link_to 'Request Access', polymorphic_path([:request_access, source, :members]),
method: :post, method: :post,
......
- if members.any? - if requesters.any?
.panel.panel-default .panel.panel-default
.panel-heading .panel-heading
%strong= membership_source.name %strong= membership_source.name
access requests access requests
%span.badge= members.size %span.badge= requesters.size
%ul.content-list %ul.content-list
= render partial: 'shared/members/member', collection: members, as: :member = render partial: 'shared/members/member', collection: requesters, as: :member
...@@ -162,7 +162,6 @@ if Settings.ldap['enabled'] || Rails.env.test? ...@@ -162,7 +162,6 @@ if Settings.ldap['enabled'] || Rails.env.test?
end end
end end
Settings['omniauth'] ||= Settingslogic.new({}) Settings['omniauth'] ||= Settingslogic.new({})
Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil? Settings.omniauth['enabled'] = false if Settings.omniauth['enabled'].nil?
Settings.omniauth['auto_sign_in_with_provider'] = false if Settings.omniauth['auto_sign_in_with_provider'].nil? Settings.omniauth['auto_sign_in_with_provider'] = false if Settings.omniauth['auto_sign_in_with_provider'].nil?
...@@ -256,7 +255,6 @@ Settings.gitlab['restricted_signup_domains'] ||= [] ...@@ -256,7 +255,6 @@ Settings.gitlab['restricted_signup_domains'] ||= []
Settings.gitlab['import_sources'] ||= %w[github bitbucket gitlab gitorious google_code fogbugz git gitlab_project] Settings.gitlab['import_sources'] ||= %w[github bitbucket gitlab gitorious google_code fogbugz git gitlab_project]
Settings.gitlab['trusted_proxies'] ||= [] Settings.gitlab['trusted_proxies'] ||= []
# #
# Elasticseacrh # Elasticseacrh
# #
...@@ -427,7 +425,6 @@ Settings.git['timeout'] ||= 10 ...@@ -427,7 +425,6 @@ Settings.git['timeout'] ||= 10
Settings['satellites'] ||= Settingslogic.new({}) Settings['satellites'] ||= Settingslogic.new({})
Settings.satellites['path'] = File.expand_path(Settings.satellites['path'] || "tmp/repo_satellites/", Rails.root) Settings.satellites['path'] = File.expand_path(Settings.satellites['path'] || "tmp/repo_satellites/", Rails.root)
# #
# Kerberos # Kerberos
# #
......
...@@ -141,7 +141,6 @@ Rails.application.routes.draw do ...@@ -141,7 +141,6 @@ Rails.application.routes.draw do
# #
resources :notification_settings, only: [:create, :update] resources :notification_settings, only: [:create, :update]
# #
# Import # Import
# #
...@@ -509,7 +508,6 @@ Rails.application.routes.draw do ...@@ -509,7 +508,6 @@ Rails.application.routes.draw do
resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do
resources(:projects, constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ }, except: resources(:projects, constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ }, except:
[:new, :create, :index], path: "/") do [:new, :create, :index], path: "/") do
member do member do
put :transfer put :transfer
delete :remove_fork delete :remove_fork
......
class AddArtifactsSizeToCiBuilds < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
def change
add_column(:ci_builds, :artifacts_size, :integer)
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160621123729) do ActiveRecord::Schema.define(version: 20160628085157) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -189,6 +189,7 @@ ActiveRecord::Schema.define(version: 20160621123729) do ...@@ -189,6 +189,7 @@ ActiveRecord::Schema.define(version: 20160621123729) do
t.datetime "erased_at" t.datetime "erased_at"
t.string "environment" t.string "environment"
t.datetime "artifacts_expire_at" t.datetime "artifacts_expire_at"
t.integer "artifacts_size"
end end
add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree
......
...@@ -3,9 +3,58 @@ ...@@ -3,9 +3,58 @@
Sometimes things don't work the way they should. Here are some tips on debugging issues out Sometimes things don't work the way they should. Here are some tips on debugging issues out
in production. in production.
## The GNU Project Debugger (gdb) ## Mail not working
`gdb` is a must-have tool for debugging issues. To install on Ubuntu/Debian: A common problem is that mails are not being sent for some reason. Suppose you configured
an SMTP server, but you're not seeing mail delivered. Here's how to check the settings:
1. Run a Rails console:
```sh
sudo gitlab-rails console production
```
or for source installs:
```sh
bundle exec rails console production
```
2. Look at the ActionMailer `delivery_method` to make sure it matches what you
intended. If you configured SMTP, it should say `:smtp`. If you're using
Sendmail, it should say `:sendmail`:
```ruby
irb(main):001:0> ActionMailer::Base.delivery_method
=> :smtp
```
3. If you're using SMTP, check the mail settings:
```ruby
irb(main):002:0> ActionMailer::Base.smtp_settings
=> {:address=>"localhost", :port=>25, :domain=>"localhost.localdomain", :user_name=>nil, :password=>nil, :authentication=>nil, :enable_starttls_auto=>true}```
```
In the example above, the SMTP server is configured for the local machine. If this is intended, you may need to check your local mail
logs (e.g. `/var/log/mail.log`) for more details.
4. Send a test message via the console.
```ruby
irb(main):003:0> Notify.test_email('youremail@email.com', 'Hello World', 'This is a test message').deliver_now
```
If you do not receive an e-mail and/or see an error message, then check
your mail server settings.
## Advanced Issues
For more advanced issues, `gdb` is a must-have tool for debugging issues.
### The GNU Project Debugger (gdb)
To install on Ubuntu/Debian:
``` ```
sudo apt-get install gdb sudo apt-get install gdb
......
...@@ -448,7 +448,7 @@ Parameters: ...@@ -448,7 +448,7 @@ Parameters:
- `merge_request_id` (required) - ID of MR - `merge_request_id` (required) - ID of MR
- `merge_commit_message` (optional) - Custom merge commit message - `merge_commit_message` (optional) - Custom merge commit message
- `should_remove_source_branch` (optional) - if `true` removes the source branch - `should_remove_source_branch` (optional) - if `true` removes the source branch
- `merged_when_build_succeeds` (optional) - if `true` the MR is merged when the build succeeds - `merge_when_build_succeeds` (optional) - if `true` the MR is merged when the build succeeds
- `sha` (optional) - if present, then this SHA must match the HEAD of the source branch, otherwise the merge will fail - `sha` (optional) - if present, then this SHA must match the HEAD of the source branch, otherwise the merge will fail
```json ```json
......
...@@ -8,7 +8,7 @@ Asana - Teamwork without email ...@@ -8,7 +8,7 @@ Asana - Teamwork without email
Set Asana service for a project. Set Asana service for a project.
> This service adds commit messages as comments to Asana tasks. Once enabled, commit messages are checked for Asana task URLs (for example, `https://app.asana.com/0/123456/987654`) or task IDs starting with # (for example, `#987654`). Every task ID found will get the commit comment added to it. You can also close a task with a message containing: `fix #123456`. You can find your Api Keys here: http://developer.asana.com/documentation/#api_keys > This service adds commit messages as comments to Asana tasks. Once enabled, commit messages are checked for Asana task URLs (for example, `https://app.asana.com/0/123456/987654`) or task IDs starting with # (for example, `#987654`). Every task ID found will get the commit comment added to it. You can also close a task with a message containing: `fix #123456`. You can find your Api Keys here: https://asana.com/developers/documentation/getting-started/auth#api-key
``` ```
PUT /projects/:id/services/asana PUT /projects/:id/services/asana
......
...@@ -16,5 +16,5 @@ ...@@ -16,5 +16,5 @@
- [Trigger builds through the API](triggers/README.md) - [Trigger builds through the API](triggers/README.md)
- [Build artifacts](build_artifacts/README.md) - [Build artifacts](build_artifacts/README.md)
- [User permissions](permissions/README.md) - [User permissions](permissions/README.md)
- [API](../../api/ci/README.md) - [API](../api/ci/README.md)
- [CI services (linked docker containers)](services/README.md) - [CI services (linked docker containers)](services/README.md)
...@@ -14,3 +14,4 @@ ...@@ -14,3 +14,4 @@
- [Blog post about using GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/) - [Blog post about using GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
- [Repo's with examples for various languages](https://gitlab.com/groups/gitlab-examples) - [Repo's with examples for various languages](https://gitlab.com/groups/gitlab-examples)
- [The .gitlab-ci.yml file for GitLab itself](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml) - [The .gitlab-ci.yml file for GitLab itself](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml)
- [A collection of useful .gitlab-ci.yml templates](https://gitlab.com/gitlab-org/gitlab-ci-yml)
...@@ -21,7 +21,7 @@ We currently use three CI services to test GitLab: ...@@ -21,7 +21,7 @@ We currently use three CI services to test GitLab:
Core team has access to trigger builds if needed for GitLab CE. Core team has access to trigger builds if needed for GitLab CE.
We use [these build scripts](https://gitlab.com/gitlab-org/gitlab-ci/blob/master/doc/examples/build_script_gitlab_ce.md) for testing with GitLab CI. We use [these build scripts](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml) for testing with GitLab CI.
# Build configuration on [Semaphore](https://semaphoreapp.com/gitlabhq/gitlabhq/) for testing the [GitHub.com repo](https://github.com/gitlabhq/gitlabhq) # Build configuration on [Semaphore](https://semaphoreapp.com/gitlabhq/gitlabhq/) for testing the [GitHub.com repo](https://github.com/gitlabhq/gitlabhq)
......
...@@ -127,9 +127,15 @@ The chosen OmniAuth provider is now active and can be used to sign in to GitLab ...@@ -127,9 +127,15 @@ The chosen OmniAuth provider is now active and can be used to sign in to GitLab
This setting was introduced with version 8.7 of GitLab This setting was introduced with version 8.7 of GitLab
You can define which OmniAuth providers you want to be `external` so that all users You can define which OmniAuth providers you want to be `external` so that all users
creating accounts via these providers will not be able to have access to internal **creating accounts, or logging in via these providers** will not be able to have
projects. You will need to use the full name of the provider, like `google_oauth2` access to internal projects. You will need to use the full name of the provider,
for Google. Refer to the examples for the full names of the supported providers. like `google_oauth2` for Google. Refer to the examples for the full names of the
supported providers.
>**Note:**
If you decide to remove an OmniAuth provider from the external providers list
you will need to manually update the users that use this method to login, if you
want their accounts to be upgraded to full internal accounts.
**For Omnibus installations** **For Omnibus installations**
......
...@@ -17,7 +17,7 @@ Public projects can be cloned **without any** authentication. ...@@ -17,7 +17,7 @@ Public projects can be cloned **without any** authentication.
They will also be listed on the public access directory (`/public`). They will also be listed on the public access directory (`/public`).
**Any logged in user** will have [Guest](../permissions/permissions) **Any logged in user** will have [Guest](../permissions/permissions.md)
permissions on the repository. permissions on the repository.
### Internal projects ### Internal projects
...@@ -27,8 +27,8 @@ Internal projects can be cloned by any logged in user. ...@@ -27,8 +27,8 @@ Internal projects can be cloned by any logged in user.
They will also be listed on the public access directory (`/public`) for logged They will also be listed on the public access directory (`/public`) for logged
in users. in users.
Any logged in user will have [Guest](../permissions/permissions) permissions on Any logged in user will have [Guest](../permissions/permissions.md) permissions
the repository. on the repository.
### How to change project visibility ### How to change project visibility
......
...@@ -17,10 +17,6 @@ cat ~/.ssh/id_rsa.pub ...@@ -17,10 +17,6 @@ cat ~/.ssh/id_rsa.pub
If you see a long string starting with `ssh-rsa`, you can skip the `ssh-keygen` step. If you see a long string starting with `ssh-rsa`, you can skip the `ssh-keygen` step.
Note: It is a best practice to use a password for an SSH key, but it is not
required and you can skip creating a password by pressing enter. Note that
the password you choose here can't be altered or retrieved.
To generate a new SSH key, use the following command: To generate a new SSH key, use the following command:
```bash ```bash
ssh-keygen -t rsa -C "$your_email" ssh-keygen -t rsa -C "$your_email"
...@@ -30,6 +26,12 @@ pair and for a password. When prompted for the location and filename, just ...@@ -30,6 +26,12 @@ pair and for a password. When prompted for the location and filename, just
press enter to use the default. If you use a different name, the key will not press enter to use the default. If you use a different name, the key will not
be used automatically. be used automatically.
Note: It is a best practice to use a password for an SSH key, but it is not
required and you can skip creating a password by pressing enter.
If you want to change the password of your key later, you can use the following
command: `ssh-keygen -p <keyname>`
Use the command below to show your public key: Use the command below to show your public key:
**Windows Command Line:** **Windows Command Line:**
......
...@@ -219,6 +219,7 @@ Feature: Project Issues ...@@ -219,6 +219,7 @@ Feature: Project Issues
When I click button "Unsubscribe" When I click button "Unsubscribe"
Then I should see that I am unsubscribed Then I should see that I am unsubscribed
@javascript
Scenario: I submit new unassigned issue as guest Scenario: I submit new unassigned issue as guest
Given public project "Community" Given public project "Community"
When I visit project "Community" page When I visit project "Community" page
......
...@@ -73,14 +73,15 @@ Feature: Search ...@@ -73,14 +73,15 @@ Feature: Search
Scenario: I logout and should see project I am looking for Scenario: I logout and should see project I am looking for
Given project "Shop" is public Given project "Shop" is public
And I logout And I logout directly
And I visit dashboard search page And I visit dashboard search page
And I search for "Sho" And I search for "Sho"
Then I should see "Shop" project link Then I should see "Shop" project link
Scenario: I logout and should see issues I am looking for Scenario: I logout and should see issues I am looking for
Given project "Shop" is public Given project "Shop" is public
And I logout And I logout directly
And I visit dashboard search page
And project has issues And project has issues
And I visit dashboard search page And I visit dashboard search page
When I search for "Foo" When I search for "Foo"
...@@ -90,7 +91,7 @@ Feature: Search ...@@ -90,7 +91,7 @@ Feature: Search
Scenario: I logout and should see project code I am looking for Scenario: I logout and should see project code I am looking for
Given project "Shop" is public Given project "Shop" is public
And I logout And I logout directly
When I visit project "Shop" page When I visit project "Shop" page
And I search for "rspec" on project page And I search for "rspec" on project page
Then I should see code results for project "Shop" Then I should see code results for project "Shop"
...@@ -49,5 +49,4 @@ class Spinach::Features::NewProject < Spinach::FeatureSteps ...@@ -49,5 +49,4 @@ class Spinach::Features::NewProject < Spinach::FeatureSteps
step 'I redirected to Google Code import page' do step 'I redirected to Google Code import page' do
expect(current_path).to eq new_import_google_code_path expect(current_path).to eq new_import_google_code_path
end end
end end
...@@ -69,7 +69,6 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps ...@@ -69,7 +69,6 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
visit namespace_project_issues_path(public_project.namespace, public_project) visit namespace_project_issues_path(public_project.namespace, public_project)
end end
step 'I should see list of issues for "Community" project' do step 'I should see list of issues for "Community" project' do
expect(page).to have_content "Bug" expect(page).to have_content "Bug"
expect(page).to have_content public_project.name expect(page).to have_content public_project.name
...@@ -88,7 +87,6 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps ...@@ -88,7 +87,6 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
visit namespace_project_issues_path(internal_project.namespace, internal_project) visit namespace_project_issues_path(internal_project.namespace, internal_project)
end end
step 'I should see list of issues for "Internal" project' do step 'I should see list of issues for "Internal" project' do
expect(page).to have_content "Internal Bug" expect(page).to have_content "Internal Bug"
expect(page).to have_content internal_project.name expect(page).to have_content internal_project.name
...@@ -137,7 +135,6 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps ...@@ -137,7 +135,6 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
@public_project ||= Project.find_by!(name: 'Community') @public_project ||= Project.find_by!(name: 'Community')
end end
def internal_merge_request def internal_merge_request
@internal_merge_request ||= MergeRequest.find_by!(title: 'Feature implemented') @internal_merge_request ||= MergeRequest.find_by!(title: 'Feature implemented')
end end
......
...@@ -33,5 +33,4 @@ class Spinach::Features::ProjectArchived < Spinach::FeatureSteps ...@@ -33,5 +33,4 @@ class Spinach::Features::ProjectArchived < Spinach::FeatureSteps
When 'I set project unarchived' do When 'I set project unarchived' do
click_link "Unarchive" click_link "Unarchive"
end end
end end
...@@ -124,14 +124,12 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps ...@@ -124,14 +124,12 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
end end
step 'project "Shop" has milestone "v2.2"' do step 'project "Shop" has milestone "v2.2"' do
milestone = create(:milestone, title: "v2.2", project: project) milestone = create(:milestone, title: "v2.2", project: project)
3.times { create(:issue, project: project, milestone: milestone) } 3.times { create(:issue, project: project, milestone: milestone) }
end end
step 'project "Shop" has milestone "v3.0"' do step 'project "Shop" has milestone "v3.0"' do
milestone = create(:milestone, title: "v3.0", project: project) milestone = create(:milestone, title: "v3.0", project: project)
3.times { create(:issue, project: project, milestone: milestone) } 3.times { create(:issue, project: project, milestone: milestone) }
...@@ -147,7 +145,6 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps ...@@ -147,7 +145,6 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
end end
When 'I select first assignee from "Shop" project' do When 'I select first assignee from "Shop" project' do
first_assignee = project.users.first first_assignee = project.users.first
select first_assignee.name, from: "assignee_id" select first_assignee.name, from: "assignee_id"
end end
...@@ -160,7 +157,6 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps ...@@ -160,7 +157,6 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
end end
step 'project "Shop" have "Release 0.4" open issue' do step 'project "Shop" have "Release 0.4" open issue' do
create(:issue, create(:issue,
title: "Release 0.4", title: "Release 0.4",
project: project, project: project,
...@@ -360,5 +356,4 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps ...@@ -360,5 +356,4 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
def filter_issue(text) def filter_issue(text)
fill_in 'issue_search', with: text fill_in 'issue_search', with: text
end end
end end
...@@ -66,7 +66,6 @@ class Spinach::Features::ProjectFindFile < Spinach::FeatureSteps ...@@ -66,7 +66,6 @@ class Spinach::Features::ProjectFindFile < Spinach::FeatureSteps
expect(page).not_to have_content(".gitignore") expect(page).not_to have_content(".gitignore")
end end
def find_file(text) def find_file(text)
fill_in 'file_find', with: text fill_in 'file_find', with: text
end end
......
...@@ -189,5 +189,4 @@ module SharedIssuable ...@@ -189,5 +189,4 @@ module SharedIssuable
expect(page).to have_content content expect(page).to have_content content
end end
end end
end end
...@@ -52,5 +52,4 @@ class Spinach::Features::SnippetSearch < Spinach::FeatureSteps ...@@ -52,5 +52,4 @@ class Spinach::Features::SnippetSearch < Spinach::FeatureSteps
step 'I should not see "Personal snippet private" in results' do step 'I should not see "Personal snippet private" in results' do
expect(page).not_to have_content 'Personal snippet private' expect(page).not_to have_content 'Personal snippet private'
end end
end end
...@@ -11,7 +11,6 @@ module API ...@@ -11,7 +11,6 @@ module API
[ ":id/#{awardable_string}/:#{awardable_id_string}/award_emoji", [ ":id/#{awardable_string}/:#{awardable_id_string}/award_emoji",
":id/#{awardable_string}/:#{awardable_id_string}/notes/:note_id/award_emoji" ":id/#{awardable_string}/:#{awardable_id_string}/notes/:note_id/award_emoji"
].each do |endpoint| ].each do |endpoint|
# Get a list of project +awardable+ award emoji # Get a list of project +awardable+ award emoji
# #
# Parameters: # Parameters:
......
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.
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