Commit 3a52662c authored by Tomasz Maczukin's avatar Tomasz Maczukin

Merge branch 'master' into fix/visibility-level-setting-in-forked-projects

* master: (23 commits)
  Use single spaces
  Improvements to profile page UI
  Replace all usages of `git` command with configurable binary path
  Update Shell Commands doc for configurable git binary path
  Minor reformatting for Facebook integration doc
  Use proper labels for OAuth providers
  Add Facebook authentication
  Bump stamp to ~> 0.6.0
  Add extra padding between user description and links on profile page
  Fix tests
  Fix clipboard button overflow
  Apply new design for user profile page
  Improve profile page UI
  Better name for up-level links
  Fixed User sorting specs
  Only sort by IDs by default
  Added benchmark for User.all
  Add changelog entry for contacted_at
  Spread out runner contacted_at updates
  Only redirect to homepage url when its not the root url
  ...
parents 89ecba5e 95da91a6
...@@ -21,6 +21,12 @@ v 8.2.0 (unreleased) ...@@ -21,6 +21,12 @@ v 8.2.0 (unreleased)
- Add "New file" link to dropdown on project page - Add "New file" link to dropdown on project page
- Include commit logs in project search - Include commit logs in project search
- Add "added", "modified" and "removed" properties to commit object in webhook - Add "added", "modified" and "removed" properties to commit object in webhook
- Rename "Back to" links to "Go to" because its not always a case it point to place user come from
v 8.1.3
- Spread out runner contacted_at updates
- New design for user profile page
- Add Facebook authentication
v 8.1.1 v 8.1.1
- Fix cloning Wiki repositories via HTTP (Stan Hu) - Fix cloning Wiki repositories via HTTP (Stan Hu)
......
...@@ -19,6 +19,7 @@ gem 'devise-async', '~> 0.9.0' ...@@ -19,6 +19,7 @@ gem 'devise-async', '~> 0.9.0'
gem 'doorkeeper', '~> 2.1.3' gem 'doorkeeper', '~> 2.1.3'
gem 'omniauth', '~> 1.2.2' gem 'omniauth', '~> 1.2.2'
gem 'omniauth-bitbucket', '~> 0.0.2' gem 'omniauth-bitbucket', '~> 0.0.2'
gem 'omniauth-facebook', '~> 3.0.0'
gem 'omniauth-github', '~> 1.1.1' gem 'omniauth-github', '~> 1.1.1'
gem 'omniauth-gitlab', '~> 1.0.0' gem 'omniauth-gitlab', '~> 1.0.0'
gem 'omniauth-google-oauth2', '~> 0.2.0' gem 'omniauth-google-oauth2', '~> 0.2.0'
...@@ -63,7 +64,7 @@ gem 'rack-cors', '~> 0.4.0', require: 'rack/cors' ...@@ -63,7 +64,7 @@ gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
# Format dates and times # Format dates and times
# based on human-friendly examples # based on human-friendly examples
gem "stamp", '~> 0.5.0' gem "stamp", '~> 0.6.0'
# Enumeration fields # Enumeration fields
gem 'enumerize', '~> 0.7.0' gem 'enumerize', '~> 0.7.0'
......
...@@ -423,6 +423,8 @@ GEM ...@@ -423,6 +423,8 @@ GEM
multi_json (~> 1.7) multi_json (~> 1.7)
omniauth (~> 1.1) omniauth (~> 1.1)
omniauth-oauth (~> 1.0) omniauth-oauth (~> 1.0)
omniauth-facebook (3.0.0)
omniauth-oauth2 (~> 1.2)
omniauth-github (1.1.2) omniauth-github (1.1.2)
omniauth (~> 1.0) omniauth (~> 1.0)
omniauth-oauth2 (~> 1.1) omniauth-oauth2 (~> 1.1)
...@@ -689,7 +691,7 @@ GEM ...@@ -689,7 +691,7 @@ GEM
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0) sprockets (>= 2.8, < 4.0)
stamp (0.5.0) stamp (0.6.0)
state_machine (1.2.0) state_machine (1.2.0)
stringex (2.5.2) stringex (2.5.2)
systemu (2.6.5) systemu (2.6.5)
...@@ -859,6 +861,7 @@ DEPENDENCIES ...@@ -859,6 +861,7 @@ DEPENDENCIES
octokit (~> 3.7.0) octokit (~> 3.7.0)
omniauth (~> 1.2.2) omniauth (~> 1.2.2)
omniauth-bitbucket (~> 0.0.2) omniauth-bitbucket (~> 0.0.2)
omniauth-facebook (~> 3.0.0)
omniauth-github (~> 1.1.1) omniauth-github (~> 1.1.1)
omniauth-gitlab (~> 1.0.0) omniauth-gitlab (~> 1.0.0)
omniauth-google-oauth2 (~> 0.2.0) omniauth-google-oauth2 (~> 0.2.0)
...@@ -909,7 +912,7 @@ DEPENDENCIES ...@@ -909,7 +912,7 @@ DEPENDENCIES
spring-commands-spinach (~> 1.0.0) spring-commands-spinach (~> 1.0.0)
spring-commands-teaspoon (~> 0.0.2) spring-commands-teaspoon (~> 0.0.2)
sprockets (~> 2.12.3) sprockets (~> 2.12.3)
stamp (~> 0.5.0) stamp (~> 0.6.0)
state_machine (~> 1.2.0) state_machine (~> 1.2.0)
task_list (~> 1.0.2) task_list (~> 1.0.2)
teaspoon (~> 1.0.0) teaspoon (~> 1.0.0)
......
...@@ -25,7 +25,7 @@ class @Calendar ...@@ -25,7 +25,7 @@ class @Calendar
30 30
] ]
legendCellPadding: 3 legendCellPadding: 3
cellSize: $('.user-calendar').width() / 80 cellSize: $('.user-calendar').width() / 73
onClick: (date, count) -> onClick: (date, count) ->
formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate() formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
$.ajax $.ajax
......
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
} }
.cover-desc { .cover-desc {
padding: 0 $gl-padding; padding: 0 $gl-padding 3px;
color: $gl-text-color; color: $gl-text-color;
} }
......
...@@ -180,3 +180,7 @@ ...@@ -180,3 +180,7 @@
} }
} }
} }
.btn-clipboard {
border: none;
}
...@@ -387,6 +387,36 @@ table { ...@@ -387,6 +387,36 @@ table {
} }
} }
.center-middle-menu {
@include nav-menu;
padding: 0;
text-align: center;
margin: -$gl-padding;
margin-top: 0;
margin-bottom: 0;
height: 58px;
border-bottom: 1px solid $border-color;
li {
&:after {
content: "|";
color: $border-gray-light;
}
&:last-child {
&:after {
content: none;
}
}
> a {
display: inline-block;
text-transform: uppercase;
font-size: 13px;
}
}
}
.dropzone .dz-preview .dz-progress { .dropzone .dz-preview .dz-progress {
border-color: $border-color !important; border-color: $border-color !important;
} }
......
...@@ -137,6 +137,7 @@ ...@@ -137,6 +137,7 @@
&:hover, &:active, &:focus { &:hover, &:active, &:focus {
text-decoration: none; text-decoration: none;
outline: none;
} }
} }
......
...@@ -53,3 +53,25 @@ ...@@ -53,3 +53,25 @@
float: right; float: right;
font-size: 12px; font-size: 12px;
} }
.profile-link-holder {
display: inline;
&:after {
content: "\00B7";
padding: 0px 6px;
font-weight: bold;
}
&:last-child {
&:after {
content: "";
padding: 0;
}
}
a {
color: $blue-dark;
text-decoration: none;
}
}
...@@ -59,14 +59,9 @@ class ApplicationController < ActionController::Base ...@@ -59,14 +59,9 @@ class ApplicationController < ActionController::Base
end end
def authenticate_user!(*args) def authenticate_user!(*args)
# If user is not signed-in and tries to access root_path - redirect him to landing page if redirect_to_home_page_url?
# Don't redirect to the default URL to prevent endless redirections
if current_application_settings.home_page_url.present? &&
current_application_settings.home_page_url.chomp('/') != Gitlab.config.gitlab['url'].chomp('/')
if current_user.nil? && root_path == request.path
redirect_to current_application_settings.home_page_url and return redirect_to current_application_settings.home_page_url and return
end end
end
super(*args) super(*args)
end end
...@@ -346,4 +341,17 @@ class ApplicationController < ActionController::Base ...@@ -346,4 +341,17 @@ class ApplicationController < ActionController::Base
def git_import_enabled? def git_import_enabled?
current_application_settings.import_sources.include?('git') current_application_settings.import_sources.include?('git')
end end
def redirect_to_home_page_url?
# If user is not signed-in and tries to access root_path - redirect him to landing page
# Don't redirect to the default URL to prevent endless redirections
return false unless current_application_settings.home_page_url.present?
home_page_url = current_application_settings.home_page_url.chomp('/')
root_urls = [Gitlab.config.gitlab['url'].chomp('/'), root_url.chomp('/')]
return false if root_urls.include?(home_page_url)
current_user.nil? && root_path == request.path
end
end end
module AuthHelper module AuthHelper
PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2).freeze PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook).freeze
FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze
def ldap_enabled? def ldap_enabled?
......
...@@ -8,12 +8,12 @@ module Sortable ...@@ -8,12 +8,12 @@ module Sortable
included do included do
# By default all models should be ordered # By default all models should be ordered
# by created_at field starting from newest # by created_at field starting from newest
default_scope { order(created_at: :desc, id: :desc) } default_scope { order(id: :desc) }
scope :order_created_desc, -> { reorder(created_at: :desc, id: :desc) } scope :order_created_desc, -> { reorder(created_at: :desc) }
scope :order_created_asc, -> { reorder(created_at: :asc, id: :asc) } scope :order_created_asc, -> { reorder(created_at: :asc) }
scope :order_updated_desc, -> { reorder(updated_at: :desc, id: :desc) } scope :order_updated_desc, -> { reorder(updated_at: :desc) }
scope :order_updated_asc, -> { reorder(updated_at: :asc, id: :asc) } scope :order_updated_asc, -> { reorder(updated_at: :asc) }
scope :order_name_asc, -> { reorder(name: :asc) } scope :order_name_asc, -> { reorder(name: :asc) }
scope :order_name_desc, -> { reorder(name: :desc) } scope :order_name_desc, -> { reorder(name: :desc) }
end end
......
...@@ -89,7 +89,7 @@ class Repository ...@@ -89,7 +89,7 @@ class Repository
def find_commits_by_message(query) def find_commits_by_message(query)
# Limited to 1000 commits for now, could be parameterized? # Limited to 1000 commits for now, could be parameterized?
args = %W(git log --pretty=%H --max-count 1000 --grep=#{query}) args = %W(#{Gitlab.config.git.bin_path} log --pretty=%H --max-count 1000 --grep=#{query})
git_log_results = Gitlab::Popen.popen(args, path_to_repo).first.lines.map(&:chomp) git_log_results = Gitlab::Popen.popen(args, path_to_repo).first.lines.map(&:chomp)
commits = git_log_results.map { |c| commit(c) } commits = git_log_results.map { |c| commit(c) }
...@@ -296,7 +296,7 @@ class Repository ...@@ -296,7 +296,7 @@ class Repository
end end
def last_commit_for_path(sha, path) def last_commit_for_path(sha, path)
args = %W(git rev-list --max-count=1 #{sha} -- #{path}) args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path})
sha = Gitlab::Popen.popen(args, path_to_repo).first.strip sha = Gitlab::Popen.popen(args, path_to_repo).first.strip
commit(sha) commit(sha)
end end
...@@ -347,7 +347,7 @@ class Repository ...@@ -347,7 +347,7 @@ class Repository
end end
def branch_names_contains(sha) def branch_names_contains(sha)
args = %W(git branch --contains #{sha}) args = %W(#{Gitlab.config.git.bin_path} branch --contains #{sha})
names = Gitlab::Popen.popen(args, path_to_repo).first names = Gitlab::Popen.popen(args, path_to_repo).first
if names.respond_to?(:split) if names.respond_to?(:split)
...@@ -364,7 +364,7 @@ class Repository ...@@ -364,7 +364,7 @@ class Repository
end end
def tag_names_contains(sha) def tag_names_contains(sha)
args = %W(git tag --contains #{sha}) args = %W(#{Gitlab.config.git.bin_path} tag --contains #{sha})
names = Gitlab::Popen.popen(args, path_to_repo).first names = Gitlab::Popen.popen(args, path_to_repo).first
if names.respond_to?(:split) if names.respond_to?(:split)
...@@ -505,7 +505,7 @@ class Repository ...@@ -505,7 +505,7 @@ class Repository
def search_files(query, ref) def search_files(query, ref)
offset = 2 offset = 2
args = %W(git grep -i -n --before-context #{offset} --after-context #{offset} -e #{query} #{ref || root_ref}) args = %W(#{Gitlab.config.git.bin_path} grep -i -n --before-context #{offset} --after-context #{offset} -e #{query} #{ref || root_ref})
Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/) Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/)
end end
...@@ -537,7 +537,7 @@ class Repository ...@@ -537,7 +537,7 @@ class Repository
end end
def fetch_ref(source_path, source_ref, target_ref) def fetch_ref(source_path, source_ref, target_ref)
args = %W(git fetch -f #{source_path} #{source_ref}:#{target_ref}) args = %W(#{Gitlab.config.git.bin_path} fetch -f #{source_path} #{source_ref}:#{target_ref})
Gitlab::Popen.popen(args, path_to_repo) Gitlab::Popen.popen(args, path_to_repo)
end end
......
...@@ -94,8 +94,6 @@ module Projects ...@@ -94,8 +94,6 @@ module Projects
@project.team << [current_user, :master, current_user] @project.team << [current_user, :master, current_user]
end end
@project.update_column(:last_activity_at, @project.created_at)
if @project.import? if @project.import?
@project.import_start @project.import_start
end end
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link do = nav_link do
= link_to root_path, title: 'Back to dashboard', data: {placement: 'right'}, class: 'back-link' do = link_to root_path, title: 'Go to dashboard', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw') = icon('caret-square-o-left fw')
%span %span
Back to dashboard Go to dashboard
%li.separate-item %li.separate-item
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link do = nav_link do
= link_to group_path(@group), title: 'Back to group', data: {placement: 'right'}, class: 'back-link' do = link_to group_path(@group), title: 'Go to group', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw') = icon('caret-square-o-left fw')
%span %span
Back to group Go to group
%li.separate-item %li.separate-item
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link do = nav_link do
= link_to root_path, title: 'Back to dashboard', data: {placement: 'right'}, class: 'back-link' do = link_to root_path, title: 'Go to dashboard', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw') = icon('caret-square-o-left fw')
%span %span
Back to dashboard Go to dashboard
%li.separate-item %li.separate-item
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
- if @project.group - if @project.group
= nav_link do = nav_link do
= link_to group_path(@project.group), title: 'Back to group', data: {placement: 'right'}, class: 'back-link' do = link_to group_path(@project.group), title: 'Go to group', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw') = icon('caret-square-o-left fw')
%span %span
Back to group Go to group
- else - else
= nav_link do = nav_link do
= link_to root_path, title: 'Back to dashboard', data: {placement: 'right'}, class: 'back-link' do = link_to root_path, title: 'Go to dashboard', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw') = icon('caret-square-o-left fw')
%span %span
Back to dashboard Go to dashboard
%li.separate-item %li.separate-item
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link do = nav_link do
= link_to project_path(@project), title: 'Back to project', data: {placement: 'right'}, class: 'back-link' do = link_to project_path(@project), title: 'Go to project', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw') = icon('caret-square-o-left fw')
%span %span
Back to project Go to project
%li.separate-item %li.separate-item
......
- if local_assigns.has_key?(:contributed_projects) && contributed_projects.present?
.panel.panel-default.contributed-projects
.panel-heading Projects contributed to
= render 'shared/projects/list',
projects: contributed_projects.sort_by(&:star_count).reverse,
projects_limit: 5, stars: true, avatar: false
- if local_assigns.has_key?(:projects) && projects.present?
.panel.panel-default
.panel-heading Personal projects
= render 'shared/projects/list',
projects: projects.sort_by(&:star_count).reverse,
projects_limit: 10, stars: true, avatar: false
...@@ -24,21 +24,26 @@ ...@@ -24,21 +24,26 @@
.cover-desc .cover-desc
- unless @user.public_email.blank? - unless @user.public_email.blank?
.profile-link-holder
= link_to @user.public_email, "mailto:#{@user.public_email}" = link_to @user.public_email, "mailto:#{@user.public_email}"
- unless @user.skype.blank? - unless @user.skype.blank?
&middot; .profile-link-holder
= link_to "Skype", "skype:#{@user.skype}" = link_to "skype:#{@user.skype}", title: "Skype" do
= icon('skype')
- unless @user.linkedin.blank? - unless @user.linkedin.blank?
&middot; .profile-link-holder
= link_to "LinkedIn", "http://www.linkedin.com/in/#{@user.linkedin}" = link_to "http://www.linkedin.com/in/#{@user.linkedin}", title: "LinkedIn" do
= icon('linkedin-square')
- unless @user.twitter.blank? - unless @user.twitter.blank?
&middot; .profile-link-holder
= link_to "Twitter", "http://www.twitter.com/#{@user.twitter}" = link_to "http://www.twitter.com/#{@user.twitter}", title: "Twitter" do
= icon('twitter-square')
- unless @user.website_url.blank? - unless @user.website_url.blank?
&middot; .profile-link-holder
= link_to @user.short_website_url, @user.full_website_url = link_to @user.short_website_url, @user.full_website_url
- unless @user.location.blank? - unless @user.location.blank?
&middot; .profile-link-holder
= icon('map-marker')
= @user.location = @user.location
...@@ -47,7 +52,7 @@ ...@@ -47,7 +52,7 @@
= link_to profile_path, class: 'btn btn-gray' do = link_to profile_path, class: 'btn btn-gray' do
= icon('pencil') = icon('pencil')
- elsif current_user - elsif current_user
.report-abuse %span.report-abuse
- if @user.abuse_report - if @user.abuse_report
%button.btn.btn-danger{ title: 'Already reported for abuse', %button.btn.btn-danger{ title: 'Already reported for abuse',
data: { toggle: 'tooltip', placement: 'left', container: 'body' }} data: { toggle: 'tooltip', placement: 'left', container: 'body' }}
...@@ -56,6 +61,10 @@ ...@@ -56,6 +61,10 @@
= link_to new_abuse_report_path(user_id: @user.id), class: 'btn btn-gray', = link_to new_abuse_report_path(user_id: @user.id), class: 'btn btn-gray',
title: 'Report abuse', data: {toggle: 'tooltip', placement: 'left', container: 'body'} do title: 'Report abuse', data: {toggle: 'tooltip', placement: 'left', container: 'body'} do
= icon('exclamation-circle') = icon('exclamation-circle')
- if current_user
&nbsp;
= link_to user_path(@user, :atom, { private_token: current_user.private_token }), class: 'btn btn-gray' do
= icon('rss')
.gray-content-block.second-block .gray-content-block.second-block
.user-calendar .user-calendar
...@@ -64,27 +73,47 @@ ...@@ -64,27 +73,47 @@
.user-calendar-activities .user-calendar-activities
.row.prepend-top-20 %ul.center-middle-menu
%section.col-md-7 %li.active
= link_to "#activity", 'data-toggle' => 'tab' do
Activity
- if @groups.any? - if @groups.any?
.prepend-top-20 %li
%h4 Groups = link_to "#groups", 'data-toggle' => 'tab' do
= render 'groups', groups: @groups Groups
%hr - if @contributed_projects.present?
%li
%h4 = link_to "#contributed", 'data-toggle' => 'tab' do
User Activity Contributed projects
- if @projects.present?
- if current_user %li
%span.rss-icon.pull-right = link_to "#personal", 'data-toggle' => 'tab' do
= link_to user_path(@user, :atom, { private_token: current_user.private_token }) do Personal projects
%strong
%i.fa.fa-rss
.tab-content
.tab-pane.active#activity
.content_list .content_list
= spinner = spinner
%aside.col-md-5
= render 'projects', projects: @projects, contributed_projects: @contributed_projects - if @groups.any?
.tab-pane#groups
%ul.content-list
- @groups.each do |group|
= render 'shared/groups/group', group: group
- if @contributed_projects.present?
.tab-pane#contributed
.contributed-projects
= render 'shared/projects/list',
projects: @contributed_projects.sort_by(&:star_count).reverse,
projects_limit: 5, stars: true, avatar: true
- if @projects.present?
.tab-pane#personal
.personal-projects
= render 'shared/projects/list',
projects: @projects.sort_by(&:star_count).reverse,
projects_limit: 10, stars: true, avatar: true
:coffeescript :coffeescript
$(".user-calendar").load("#{user_calendar_path}") $(".user-calendar").load("#{user_calendar_path}")
...@@ -274,27 +274,28 @@ production: &base ...@@ -274,27 +274,28 @@ production: &base
# arguments, followed by optional 'args' which can be either a hash or an array. # arguments, followed by optional 'args' which can be either a hash or an array.
# Documentation for this is available at http://doc.gitlab.com/ce/integration/omniauth.html # Documentation for this is available at http://doc.gitlab.com/ce/integration/omniauth.html
providers: providers:
# - { name: 'google_oauth2',
# label: 'Google',
# app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET',
# args: { access_type: 'offline', approval_prompt: '' } }
# - { name: 'twitter',
# app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET' }
# - { name: 'github', # - { name: 'github',
# label: 'GitHub',
# app_id: 'YOUR_APP_ID', # app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET', # app_secret: 'YOUR_APP_SECRET',
# args: { scope: 'user:email' } } # args: { scope: 'user:email' } }
# - { name: 'bitbucket',
# app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET' }
# - { name: 'gitlab', # - { name: 'gitlab',
# label: 'GitLab.com',
# app_id: 'YOUR_APP_ID', # app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET', # app_secret: 'YOUR_APP_SECRET',
# args: { scope: 'api' } } # args: { scope: 'api' } }
# - { name: 'bitbucket', # - { name: 'google_oauth2',
# app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET',
# args: { access_type: 'offline', approval_prompt: '' } }
# - { name: 'facebook',
# app_id: 'YOUR_APP_ID', # app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET' } # app_secret: 'YOUR_APP_SECRET' }
# - { name: 'twitter',
# app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET' }
#
# - { name: 'saml', # - { name: 'saml',
# label: 'Our SAML Provider', # label: 'Our SAML Provider',
# args: { # args: {
......
module Gitlab module Gitlab
VERSION = File.read(Rails.root.join("VERSION")).strip
REVISION = Gitlab::Popen.popen(%W(git log --pretty=format:%h -n 1)).first.chomp
def self.config def self.config
Settings Settings
end end
VERSION = File.read(Rails.root.join("VERSION")).strip
REVISION = Gitlab::Popen.popen(%W(#{config.git.bin_path} log --pretty=format:%h -n 1)).first.chomp
end end
class AddServicesTemplateIndex < ActiveRecord::Migration
def change
add_index :services, :template
end
end
...@@ -667,6 +667,7 @@ ActiveRecord::Schema.define(version: 20151026182941) do ...@@ -667,6 +667,7 @@ ActiveRecord::Schema.define(version: 20151026182941) do
add_index "services", ["created_at", "id"], name: "index_services_on_created_at_and_id", using: :btree add_index "services", ["created_at", "id"], name: "index_services_on_created_at_and_id", using: :btree
add_index "services", ["project_id"], name: "index_services_on_project_id", using: :btree add_index "services", ["project_id"], name: "index_services_on_project_id", using: :btree
add_index "services", ["template"], name: "index_services_on_template", using: :btree
create_table "snippets", force: true do |t| create_table "snippets", force: true do |t|
t.string "title" t.string "title"
......
...@@ -35,6 +35,16 @@ Gitlab::Popen.popen(%W(find /some/path -not -path /some/path -mmin +120 -delete) ...@@ -35,6 +35,16 @@ Gitlab::Popen.popen(%W(find /some/path -not -path /some/path -mmin +120 -delete)
This coding style could have prevented CVE-2013-4490. This coding style could have prevented CVE-2013-4490.
## Always use the configurable git binary path for git commands
```ruby
# Wrong
system(*%W(git branch -d -- #{branch_name}))
# Correct
system(*%W(#{Gitlab.config.git.bin_path} branch -d -- #{branch_name}))
```
## Bypass the shell by splitting commands into separate tokens ## Bypass the shell by splitting commands into separate tokens
When we pass shell commands as a single string to Ruby, Ruby will let `/bin/sh` evaluate the entire string. Essentially, we are asking the shell to evaluate a one-line script. This creates a risk for shell injection attacks. It is better to split the shell command into tokens ourselves. Sometimes we use the scripting capabilities of the shell to change the working directory or set environment variables. All of this can also be achieved securely straight from Ruby When we pass shell commands as a single string to Ruby, Ruby will let `/bin/sh` evaluate the entire string. Essentially, we are asking the shell to evaluate a one-line script. This creates a risk for shell injection attacks. It is better to split the shell command into tokens ourselves. Sometimes we use the scripting capabilities of the shell to change the working directory or set environment variables. All of this can also be achieved securely straight from Ruby
...@@ -81,9 +91,9 @@ In the GitLab codebase, we avoid the option/argument ambiguity by _always_ using ...@@ -81,9 +91,9 @@ In the GitLab codebase, we avoid the option/argument ambiguity by _always_ using
```ruby ```ruby
# Wrong # Wrong
system(*%W(git branch -d #{branch_name})) system(*%W(#{Gitlab.config.git.bin_path} branch -d #{branch_name}))
# Correct # Correct
system(*%W(git branch -d -- #{branch_name})) system(*%W(#{Gitlab.config.git.bin_path} branch -d -- #{branch_name}))
``` ```
This coding style could have prevented CVE-2013-4582. This coding style could have prevented CVE-2013-4582.
...@@ -94,9 +104,9 @@ Capturing the output of shell commands with backticks reads nicely, but you are ...@@ -94,9 +104,9 @@ Capturing the output of shell commands with backticks reads nicely, but you are
```ruby ```ruby
# Wrong # Wrong
logs = `cd #{repo_dir} && git log` logs = `cd #{repo_dir} && #{Gitlab.config.git.bin_path} log`
# Correct # Correct
logs, exit_status = Gitlab::Popen.popen(%W(git log), repo_dir) logs, exit_status = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} log), repo_dir)
# Wrong # Wrong
user = `whoami` user = `whoami`
...@@ -108,7 +118,7 @@ In other repositories, such as gitlab-shell you can also use `IO.popen`. ...@@ -108,7 +118,7 @@ In other repositories, such as gitlab-shell you can also use `IO.popen`.
```ruby ```ruby
# Safe IO.popen example # Safe IO.popen example
logs = IO.popen(%W(git log), chdir: repo_dir) { |p| p.read } logs = IO.popen(%W(#{Gitlab.config.git.bin_path} log), chdir: repo_dir) { |p| p.read }
``` ```
Note that unlike `Gitlab::Popen.popen`, `IO.popen` does not capture standard error. Note that unlike `Gitlab::Popen.popen`, `IO.popen` does not capture standard error.
......
# Facebook OAuth2 OmniAuth Provider
To enable the Facebook OmniAuth provider you must register your application with Facebook. Facebook will generate an app ID and secret key for you to use.
1. Sign in to the [Facebook Developer Platform](https://developers.facebook.com/).
1. Choose "My Apps" &gt; "Add a New App"
1. Select the type "Website"
1. Enter a name for your app. This can be anything. Consider something like "&lt;Organization&gt;'s GitLab" or "&lt;Your Name&gt;'s GitLab" or
something else descriptive.
1. Choose "Create New Facebook App ID"
1. Select a Category, for example "Productivity"
1. Choose "Create App ID"
1. Enter the address of your GitLab installation at the bottom of the package
![Facebook Website URL](facebook_website_url.png)
1. Choose "Next"
1. Choose "Skip Quick Start" in the upper right corner
1. Choose "Settings" in the menu on the left
1. Fill in a contact email for your app
![Facebook App Settings](facebook_app_settings.png)
1. Choose "Save Changes"
1. Choose "Status & Review" in the menu on the left
1. Change the switch on the right from No to Yes
1. Choose "Confirm" when prompted to make the app public
1. Choose "Dashboard" in the menu on the left
1. Choose "Show" next to the hidden "App Secret"
1. You should now see an app key and app secret (see screenshot). Keep this page open as you continue configuration.
![Facebook API Keys](facebook_api_keys.png)
1. On your GitLab server, open the configuration file.
For omnibus package:
```sh
sudo editor /etc/gitlab/gitlab.rb
```
For installations from source:
```sh
cd /home/git/gitlab
sudo -u git -H editor config/gitlab.yml
```
1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
1. Add the provider configuration:
For omnibus package:
```ruby
gitlab_rails['omniauth_providers'] = [
{
"name" => "facebook",
"app_id" => "YOUR_APP_ID",
"app_secret" => "YOUR_APP_SECRET"
}
]
```
For installations from source:
```
- { name: 'facebook', app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET' }
```
1. Change 'YOUR_APP_ID' to the API key from Facebook page in step 10.
1. Change 'YOUR_APP_SECRET' to the API secret from the Facebook page in step 10.
1. Save the configuration file.
1. Restart GitLab for the changes to take effect.
On the sign in page there should now be a Facebook icon below the regular sign in form. Click the icon to begin the authentication process. Facebook will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in.
...@@ -73,8 +73,9 @@ Now we can choose one or more of the Supported Providers below to continue confi ...@@ -73,8 +73,9 @@ Now we can choose one or more of the Supported Providers below to continue confi
- [Bitbucket](bitbucket.md) - [Bitbucket](bitbucket.md)
- [GitLab.com](gitlab.md) - [GitLab.com](gitlab.md)
- [Google](google.md) - [Google](google.md)
- [Shibboleth](shibboleth.md) - [Facebook](facebook.md)
- [Twitter](twitter.md) - [Twitter](twitter.md)
- [Shibboleth](shibboleth.md)
- [SAML](saml.md) - [SAML](saml.md)
- [Crowd](crowd.md) - [Crowd](crowd.md)
......
...@@ -15,6 +15,8 @@ For subtitles, use '##', '###' and so on. ...@@ -15,6 +15,8 @@ For subtitles, use '##', '###' and so on.
- Do not duplicate information. - Do not duplicate information.
- Be brief and clear. - Be brief and clear.
- Whenever it applies, add documents in alphabetical order. - Whenever it applies, add documents in alphabetical order.
- Write in US English
- Use [single spaces](http://www.slate.com/articles/technology/technology/2011/01/space_invaders.html) instead of double spaces.
## Images ## Images
......
...@@ -7,6 +7,7 @@ Feature: Profile ...@@ -7,6 +7,7 @@ Feature: Profile
Given I visit profile page Given I visit profile page
Then I should see my profile info Then I should see my profile info
@javascript
Scenario: I can see groups I belong to Scenario: I can see groups I belong to
Given I have group with projects Given I have group with projects
When I visit profile page When I visit profile page
......
...@@ -6,7 +6,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps ...@@ -6,7 +6,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
include Select2Helper include Select2Helper
step 'I should see back to dashboard button' do step 'I should see back to dashboard button' do
expect(page).to have_content 'Back to dashboard' expect(page).to have_content 'Go to dashboard'
end end
step 'gitlab user "Mike"' do step 'gitlab user "Mike"' do
......
...@@ -159,10 +159,9 @@ class Spinach::Features::Profile < Spinach::FeatureSteps ...@@ -159,10 +159,9 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
end end
step 'I should see my user page' do step 'I should see my user page' do
expect(page).to have_content "User Activity" page.within ".cover-block" do
page.within '.navbar-gitlab' do
expect(page).to have_content current_user.name expect(page).to have_content current_user.name
expect(page).to have_content current_user.username
end end
end end
...@@ -176,7 +175,13 @@ class Spinach::Features::Profile < Spinach::FeatureSteps ...@@ -176,7 +175,13 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
end end
step 'I should see groups I belong to' do step 'I should see groups I belong to' do
expect(page).to have_css('.profile-groups-avatars', visible: true) page.within ".content" do
click_link "Groups"
end
page.within "#groups" do
expect(page).to have_content @group.name
end
end end
step 'I click on new application button' do step 'I click on new application button' do
......
...@@ -124,11 +124,11 @@ class Spinach::Features::Project < Spinach::FeatureSteps ...@@ -124,11 +124,11 @@ class Spinach::Features::Project < Spinach::FeatureSteps
end end
step 'I should see back to dashboard button' do step 'I should see back to dashboard button' do
expect(page).to have_content 'Back to dashboard' expect(page).to have_content 'Go to dashboard'
end end
step 'I should see back to group button' do step 'I should see back to group button' do
expect(page).to have_content 'Back to group' expect(page).to have_content 'Go to group'
end end
step 'I click notifications drop down button' do step 'I click notifications drop down button' do
......
...@@ -46,7 +46,7 @@ module SharedProjectTab ...@@ -46,7 +46,7 @@ module SharedProjectTab
step 'the active main tab should be Settings' do step 'the active main tab should be Settings' do
page.within '.nav-sidebar' do page.within '.nav-sidebar' do
expect(page).to have_content('Back to project') expect(page).to have_content('Go to project')
end end
end end
......
...@@ -35,7 +35,7 @@ module Backup ...@@ -35,7 +35,7 @@ module Backup
if wiki.repository.empty? if wiki.repository.empty?
$progress.puts " [SKIPPED]".cyan $progress.puts " [SKIPPED]".cyan
else else
cmd = %W(git --git-dir=#{path_to_repo(wiki)} bundle create #{path_to_bundle(wiki)} --all) cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path_to_repo(wiki)} bundle create #{path_to_bundle(wiki)} --all)
output, status = Gitlab::Popen.popen(cmd) output, status = Gitlab::Popen.popen(cmd)
if status.zero? if status.zero?
$progress.puts " [DONE]".green $progress.puts " [DONE]".green
...@@ -67,7 +67,7 @@ module Backup ...@@ -67,7 +67,7 @@ module Backup
FileUtils.mkdir_p(path_to_repo(project)) FileUtils.mkdir_p(path_to_repo(project))
cmd = %W(tar -xf #{path_to_bundle(project)} -C #{path_to_repo(project)}) cmd = %W(tar -xf #{path_to_bundle(project)} -C #{path_to_repo(project)})
else else
cmd = %W(git init --bare #{path_to_repo(project)}) cmd = %W(#{Gitlab.config.git.bin_path} init --bare #{path_to_repo(project)})
end end
if system(*cmd, silent) if system(*cmd, silent)
...@@ -87,7 +87,7 @@ module Backup ...@@ -87,7 +87,7 @@ module Backup
# that was initialized with ProjectWiki.new() and then # that was initialized with ProjectWiki.new() and then
# try to restore with 'git clone --bare'. # try to restore with 'git clone --bare'.
FileUtils.rm_rf(path_to_repo(wiki)) FileUtils.rm_rf(path_to_repo(wiki))
cmd = %W(git clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)}) cmd = %W(#{Gitlab.config.git.bin_path} clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)})
if system(*cmd, silent) if system(*cmd, silent)
$progress.puts " [DONE]".green $progress.puts " [DONE]".green
......
...@@ -16,7 +16,9 @@ module Ci ...@@ -16,7 +16,9 @@ module Ci
end end
def update_runner_last_contact def update_runner_last_contact
if current_runner.contacted_at.nil? || Time.now - current_runner.contacted_at >= UPDATE_RUNNER_EVERY # Use a random threshold to prevent beating DB updates
contacted_at_max_age = UPDATE_RUNNER_EVERY + Random.rand(UPDATE_RUNNER_EVERY)
if current_runner.contacted_at.nil? || Time.now - current_runner.contacted_at >= contacted_at_max_age
current_runner.update_attributes(contacted_at: Time.now) current_runner.update_attributes(contacted_at: Time.now)
end end
end end
......
...@@ -7,7 +7,7 @@ module Gitlab ...@@ -7,7 +7,7 @@ module Gitlab
if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev) if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
false false
else else
missed_refs, _ = Gitlab::Popen.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})) missed_refs, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev}))
missed_refs.split("\n").size > 0 missed_refs.split("\n").size > 0
end end
end end
......
...@@ -6,7 +6,7 @@ module Gitlab ...@@ -6,7 +6,7 @@ module Gitlab
# Returns true for a valid reference name, false otherwise # Returns true for a valid reference name, false otherwise
def validate(ref_name) def validate(ref_name)
Gitlab::Utils.system_silent( Gitlab::Utils.system_silent(
%W(git check-ref-format refs/#{ref_name})) %W(#{Gitlab.config.git.bin_path} check-ref-format refs/#{ref_name}))
end end
end end
end end
module Gitlab module Gitlab
module OAuth module OAuth
class Provider class Provider
LABELS = {
"github" => "GitHub",
"gitlab" => "GitLab.com",
"google_oauth2" => "Google"
}.freeze
def self.providers def self.providers
Devise.omniauth_providers Devise.omniauth_providers
end end
...@@ -23,8 +29,9 @@ module Gitlab ...@@ -23,8 +29,9 @@ module Gitlab
end end
def self.label_for(name) def self.label_for(name)
name = name.to_s
config = config_for(name) config = config_for(name)
(config && config['label']) || name.to_s.titleize (config && config['label']) || LABELS[name] || name.titleize
end end
end end
end end
......
...@@ -50,15 +50,15 @@ module Gitlab ...@@ -50,15 +50,15 @@ module Gitlab
end end
def fetch_git_tags def fetch_git_tags
remote_tags, _ = Gitlab::Popen.popen(%W(git ls-remote --tags https://gitlab.com/gitlab-org/gitlab-ce.git)) remote_tags, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} ls-remote --tags https://gitlab.com/gitlab-org/gitlab-ce.git))
remote_tags.split("\n").grep(/tags\/v#{current_version.major}/) remote_tags.split("\n").grep(/tags\/v#{current_version.major}/)
end end
def update_commands def update_commands
{ {
"Stash changed files" => %W(git stash), "Stash changed files" => %W(#{Gitlab.config.git.bin_path} stash),
"Get latest code" => %W(git fetch), "Get latest code" => %W(#{Gitlab.config.git.bin_path} fetch),
"Switch to new version" => %W(git checkout v#{latest_version}), "Switch to new version" => %W(#{Gitlab.config.git.bin_path} checkout v#{latest_version}),
"Install gems" => %W(bundle), "Install gems" => %W(bundle),
"Migrate DB" => %W(bundle exec rake db:migrate), "Migrate DB" => %W(bundle exec rake db:migrate),
"Recompile assets" => %W(bundle exec rake assets:clean assets:precompile), "Recompile assets" => %W(bundle exec rake assets:clean assets:precompile),
......
...@@ -824,7 +824,7 @@ namespace :gitlab do ...@@ -824,7 +824,7 @@ namespace :gitlab do
repo_dirs = Dir.glob(File.join(namespace_dir, '*')) repo_dirs = Dir.glob(File.join(namespace_dir, '*'))
repo_dirs.each do |dir| repo_dirs.each do |dir|
puts "\nChecking repo at #{dir}" puts "\nChecking repo at #{dir}"
system(*%w(git fsck), chdir: dir) system(*%W(#{Gitlab.config.git.bin_path} fsck), chdir: dir)
end end
end end
end end
......
...@@ -17,7 +17,7 @@ namespace :gitlab do ...@@ -17,7 +17,7 @@ namespace :gitlab do
# Clone if needed # Clone if needed
unless File.directory?(target_dir) unless File.directory?(target_dir)
system(*%W(git clone -- #{args.repo} #{target_dir})) system(*%W(#{Gitlab.config.git.bin_path} clone -- #{args.repo} #{target_dir}))
end end
# Make sure we're on the right tag # Make sure we're on the right tag
...@@ -27,7 +27,7 @@ namespace :gitlab do ...@@ -27,7 +27,7 @@ namespace :gitlab do
reseted = reset_to_commit(args) reseted = reset_to_commit(args)
unless reseted unless reseted
system(*%W(git fetch origin)) system(*%W(#{Gitlab.config.git.bin_path} fetch origin))
reset_to_commit(args) reset_to_commit(args)
end end
...@@ -128,14 +128,14 @@ namespace :gitlab do ...@@ -128,14 +128,14 @@ namespace :gitlab do
end end
def reset_to_commit(args) def reset_to_commit(args)
tag, status = Gitlab::Popen.popen(%W(git describe -- #{args.tag})) tag, status = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} describe -- #{args.tag}))
unless status.zero? unless status.zero?
tag, status = Gitlab::Popen.popen(%W(git describe -- origin/#{args.tag})) tag, status = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} describe -- origin/#{args.tag}))
end end
tag = tag.strip tag = tag.strip
system(*%W(git reset --hard #{tag})) system(*%W(#{Gitlab.config.git.bin_path} reset --hard #{tag}))
end end
end end
require 'spec_helper' require 'spec_helper'
describe User, benchmark: true do describe User, benchmark: true do
describe '.all' do
before do
10.times { create(:user) }
end
benchmark_subject { User.all.to_a }
it { is_expected.to iterate_per_second(500) }
end
describe '.by_login' do describe '.by_login' do
before do before do
%w{Alice Bob Eve}.each do |name| %w{Alice Bob Eve}.each do |name|
......
require 'spec_helper'
describe Projects::CreateService, benchmark: true do
describe '#execute' do
let(:user) { create(:user, :admin) }
let(:group) do
group = create(:group)
create(:group_member, group: group, user: user)
group
end
benchmark_subject do
name = SecureRandom.hex
service = described_class.new(user,
name: name,
path: name,
namespace_id: group.id,
visibility_level: Gitlab::VisibilityLevel::PUBLIC)
service.execute
end
it { is_expected.to iterate_per_second(0.5) }
end
end
...@@ -223,7 +223,7 @@ describe ProjectWiki do ...@@ -223,7 +223,7 @@ describe ProjectWiki do
def create_temp_repo(path) def create_temp_repo(path)
FileUtils.mkdir_p path FileUtils.mkdir_p path
system(*%W(git init --quiet --bare -- #{path})) system(*%W(#{Gitlab.config.git.bin_path} init --quiet --bare -- #{path}))
end end
def remove_temp_repo(path) def remove_temp_repo(path)
......
...@@ -663,24 +663,24 @@ describe User do ...@@ -663,24 +663,24 @@ describe User do
@user1 = create :user, created_at: Date.today - 1, last_sign_in_at: Date.today - 1, name: 'Omega' @user1 = create :user, created_at: Date.today - 1, last_sign_in_at: Date.today - 1, name: 'Omega'
end end
it "sorts users as recently_signed_in" do it "sorts users by the recent sign-in time" do
expect(User.sort('recent_sign_in').first).to eq(@user) expect(User.sort('recent_sign_in').first).to eq(@user)
end end
it "sorts users as late_signed_in" do it "sorts users by the oldest sign-in time" do
expect(User.sort('oldest_sign_in').first).to eq(@user1) expect(User.sort('oldest_sign_in').first).to eq(@user1)
end end
it "sorts users as recently_created" do it "sorts users in descending order by their creation time" do
expect(User.sort('created_desc').first).to eq(@user) expect(User.sort('created_desc').first).to eq(@user)
end end
it "sorts users as late_created" do it "sorts users in ascending order by their creation time" do
expect(User.sort('created_asc').first).to eq(@user1) expect(User.sort('created_asc').first).to eq(@user1)
end end
it "sorts users by name when nil is passed" do it "sorts users by id in descending order when nil is passed" do
expect(User.sort(nil).first).to eq(@user) expect(User.sort(nil).first).to eq(@user1)
end end
end end
......
...@@ -36,8 +36,8 @@ describe API::API, api: true do ...@@ -36,8 +36,8 @@ describe API::API, api: true do
it 'should create a new annotated tag' do it 'should create a new annotated tag' do
# Identity must be set in .gitconfig to create annotated tag. # Identity must be set in .gitconfig to create annotated tag.
repo_path = project.repository.path_to_repo repo_path = project.repository.path_to_repo
system(*%W(git --git-dir=#{repo_path} config user.name #{user.name})) system(*%W(#{Gitlab.config.git.bin_path} --git-dir=#{repo_path} config user.name #{user.name}))
system(*%W(git --git-dir=#{repo_path} config user.email #{user.email})) system(*%W(#{Gitlab.config.git.bin_path} --git-dir=#{repo_path} config user.email #{user.email}))
post api("/projects/#{project.id}/repository/tags", user), post api("/projects/#{project.id}/repository/tags", user),
tag_name: 'v7.1.0', tag_name: 'v7.1.0',
......
...@@ -96,15 +96,15 @@ module TestEnv ...@@ -96,15 +96,15 @@ module TestEnv
clone_url = "https://gitlab.com/gitlab-org/#{repo_name}.git" clone_url = "https://gitlab.com/gitlab-org/#{repo_name}.git"
unless File.directory?(repo_path) unless File.directory?(repo_path)
system(*%W(git clone -q #{clone_url} #{repo_path})) system(*%W(#{Gitlab.config.git.bin_path} clone -q #{clone_url} #{repo_path}))
end end
Dir.chdir(repo_path) do Dir.chdir(repo_path) do
branch_sha.each do |branch, sha| branch_sha.each do |branch, sha|
# Try to reset without fetching to avoid using the network. # Try to reset without fetching to avoid using the network.
reset = %W(git update-ref refs/heads/#{branch} #{sha}) reset = %W(#{Gitlab.config.git.bin_path} update-ref refs/heads/#{branch} #{sha})
unless system(*reset) unless system(*reset)
if system(*%w(git fetch origin)) if system(*%W(#{Gitlab.config.git.bin_path} fetch origin))
unless system(*reset) unless system(*reset)
raise 'The fetched test seed '\ raise 'The fetched test seed '\
'does not contain the required revision.' 'does not contain the required revision.'
...@@ -117,7 +117,7 @@ module TestEnv ...@@ -117,7 +117,7 @@ module TestEnv
end end
# We must copy bare repositories because we will push to them. # We must copy bare repositories because we will push to them.
system(git_env, *%W(git clone -q --bare #{repo_path} #{repo_path_bare})) system(git_env, *%W(#{Gitlab.config.git.bin_path} clone -q --bare #{repo_path} #{repo_path_bare}))
end end
def copy_repo(project) def copy_repo(project)
......
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