Commit 376dd3a3838622f73a444e5621257c831b284809

Authored by Dmitriy Zaporozhets
2 parents 2ee04b12 3083e5e4

Merge branch 'feature/create_file' of /home/git/repositories/gitlab/gitlabhq

app/contexts/base_context.rb
@@ -17,4 +17,3 @@ class BaseContext @@ -17,4 +17,3 @@ class BaseContext
17 abilities.allowed?(object, action, subject) 17 abilities.allowed?(object, action, subject)
18 end 18 end
19 end 19 end
20 -  
app/contexts/files/base_context.rb 0 → 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +module Files
  2 + class BaseContext < ::BaseContext
  3 + attr_reader :ref, :path
  4 +
  5 + def initialize(project, user, params, ref, path = nil)
  6 + @project, @current_user, @params = project, user, params.dup
  7 + @ref = ref
  8 + @path = path
  9 + end
  10 +
  11 + private
  12 +
  13 + def error(message)
  14 + {
  15 + error: message,
  16 + status: :error
  17 + }
  18 + end
  19 +
  20 + def success
  21 + {
  22 + error: '',
  23 + status: :success
  24 + }
  25 + end
  26 +
  27 + def repository
  28 + project.repository
  29 + end
  30 + end
  31 +end
app/contexts/files/create_context.rb 0 → 100644
@@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
  1 +module Files
  2 + class CreateContext < BaseContext
  3 + def execute
  4 + allowed = if project.protected_branch?(ref)
  5 + can?(current_user, :push_code_to_protected_branches, project)
  6 + else
  7 + can?(current_user, :push_code, project)
  8 + end
  9 +
  10 + unless allowed
  11 + return error("You are not allowed to create file in this branch")
  12 + end
  13 +
  14 + unless repository.branch_names.include?(ref)
  15 + return error("You can only create files if you are on top of a branch")
  16 + end
  17 +
  18 + file_name = params[:file_name]
  19 +
  20 + unless file_name =~ Gitlab::Regex.path_regex
  21 + return error("Your changes could not be commited, because file name contains not allowed characters")
  22 + end
  23 +
  24 + file_path = if path.blank?
  25 + file_name
  26 + else
  27 + File.join(path, file_name)
  28 + end
  29 +
  30 + blob = repository.blob_at(ref, file_path)
  31 +
  32 + if blob
  33 + return error("Your changes could not be commited, because file with such name exists")
  34 + end
  35 +
  36 + new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, path)
  37 + created_successfully = new_file_action.commit!(
  38 + params[:content],
  39 + params[:commit_message],
  40 + file_name,
  41 + )
  42 +
  43 + if created_successfully
  44 + success
  45 + else
  46 + error("Your changes could not be commited, because the file has been changed")
  47 + end
  48 + end
  49 + end
  50 +end
app/contexts/files/update_context.rb 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +module Files
  2 + class UpdateContext < BaseContext
  3 + def execute
  4 + allowed = if project.protected_branch?(ref)
  5 + can?(current_user, :push_code_to_protected_branches, project)
  6 + else
  7 + can?(current_user, :push_code, project)
  8 + end
  9 +
  10 + unless allowed
  11 + return error("You are not allowed to push into this branch")
  12 + end
  13 +
  14 + unless repository.branch_names.include?(ref)
  15 + return error("You can only create files if you are on top of a branch")
  16 + end
  17 +
  18 + blob = repository.blob_at(ref, path)
  19 +
  20 + unless blob
  21 + return error("You can only edit text files")
  22 + end
  23 +
  24 + new_file_action = Gitlab::Satellite::EditFileAction.new(current_user, project, ref, path)
  25 + created_successfully = new_file_action.commit!(
  26 + params[:content],
  27 + params[:commit_message],
  28 + params[:last_commit]
  29 + )
  30 +
  31 + if created_successfully
  32 + success
  33 + else
  34 + error("Your changes could not be commited, because the file has been changed")
  35 + end
  36 + end
  37 + end
  38 +end
app/controllers/projects/application_controller.rb
@@ -23,4 +23,10 @@ class Projects::ApplicationController &lt; ApplicationController @@ -23,4 +23,10 @@ class Projects::ApplicationController &lt; ApplicationController
23 'public_projects' 23 'public_projects'
24 end 24 end
25 end 25 end
  26 +
  27 + def require_branch_head
  28 + unless @repository.branch_names.include?(@ref)
  29 + redirect_to project_tree_path(@project, @ref), notice: "This action is not allowed unless you are on top of a branch"
  30 + end
  31 + end
26 end 32 end
app/controllers/projects/base_tree_controller.rb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +class Projects::BaseTreeController < Projects::ApplicationController
  2 + include ExtractsPath
  3 +
  4 + before_filter :authorize_read_project!
  5 + before_filter :authorize_code_access!
  6 + before_filter :require_non_empty_project
  7 +end
  8 +
app/controllers/projects/edit_tree_controller.rb
1 -# Controller for edit a repository's file  
2 -class Projects::EditTreeController < Projects::ApplicationController  
3 - include ExtractsPath  
4 -  
5 - # Authorize  
6 - before_filter :authorize_read_project!  
7 - before_filter :authorize_code_access!  
8 - before_filter :require_non_empty_project  
9 -  
10 - before_filter :edit_requirements, only: [:show, :update] 1 +class Projects::EditTreeController < Projects::BaseTreeController
  2 + before_filter :require_branch_head
  3 + before_filter :blob
11 4
12 def show 5 def show
13 @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha 6 @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
14 end 7 end
15 8
16 def update 9 def update
17 - edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, @project, @ref, @path)  
18 - updated_successfully = edit_file_action.commit!(  
19 - params[:content],  
20 - params[:commit_message],  
21 - params[:last_commit]  
22 - ) 10 + result = Files::UpdateContext.new(@project, current_user, params, @ref, @path).execute
23 11
24 - if updated_successfully  
25 - redirect_to project_blob_path(@project, @id), notice: "Your changes have been successfully commited" 12 + if result[:status] == :success
  13 + flash[:notice] = "Your changes have been successfully commited"
  14 + redirect_to project_blob_path(@project, @id)
26 else 15 else
27 - flash[:notice] = "Your changes could not be commited, because the file has been changed" 16 + flash[:alert] = result[:error]
28 render :show 17 render :show
29 end 18 end
30 end 19 end
31 20
32 private 21 private
33 22
34 - def edit_requirements  
35 - @blob = @repository.blob_at(@commit.id, @path)  
36 -  
37 - unless @blob  
38 - redirect_to project_blob_path(@project, @id), notice: "You can only edit text files"  
39 - end  
40 -  
41 - allowed = if project.protected_branch? @ref  
42 - can?(current_user, :push_code_to_protected_branches, project)  
43 - else  
44 - can?(current_user, :push_code, project)  
45 - end  
46 -  
47 - return access_denied! unless allowed  
48 -  
49 - unless @repository.branch_names.include?(@ref)  
50 - redirect_to project_blob_path(@project, @id), notice: "You can only edit this file if you are on top of a branch"  
51 - end 23 + def blob
  24 + @blob ||= @repository.blob_at(@commit.id, @path)
52 end 25 end
53 end 26 end
app/controllers/projects/new_tree_controller.rb 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +class Projects::NewTreeController < Projects::BaseTreeController
  2 + before_filter :require_branch_head
  3 +
  4 + def show
  5 + end
  6 +
  7 + def update
  8 + result = Files::CreateContext.new(@project, current_user, params, @ref, @path).execute
  9 +
  10 + if result[:status] == :success
  11 + flash[:notice] = "Your changes have been successfully commited"
  12 + redirect_to project_blob_path(@project, File.join(@id, params[:file_name]))
  13 + else
  14 + flash[:alert] = result[:error]
  15 + render :show
  16 + end
  17 + end
  18 +end
app/controllers/projects/tree_controller.rb
1 # Controller for viewing a repository's file structure 1 # Controller for viewing a repository's file structure
2 -class Projects::TreeController < Projects::ApplicationController  
3 - include ExtractsPath  
4 -  
5 - # Authorize  
6 - before_filter :authorize_read_project!  
7 - before_filter :authorize_code_access!  
8 - before_filter :require_non_empty_project  
9 - 2 +class Projects::TreeController < Projects::BaseTreeController
10 def show 3 def show
11 return not_found! if tree.entries.empty? 4 return not_found! if tree.entries.empty?
12 5
app/views/layouts/nav/_project.html.haml
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 %i.icon-home 4 %i.icon-home
5 5
6 - if project_nav_tab? :files 6 - if project_nav_tab? :files
7 - = nav_link(controller: %w(tree blob blame edit_tree)) do 7 + = nav_link(controller: %w(tree blob blame edit_tree new_tree)) do
8 = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref) 8 = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref)
9 9
10 - if project_nav_tab? :commits 10 - if project_nav_tab? :commits
app/views/projects/new_tree/show.html.haml 0 → 100644
@@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
  1 +%h3.page-title New file
  2 +%hr
  3 +.file-editor
  4 + = form_tag(project_new_tree_path(@project, @id), method: :put, class: "form-horizontal") do
  5 + .control-group.commit_message-group
  6 + = label_tag 'file_name', class: "control-label" do
  7 + File name
  8 + .controls
  9 + %span.monospace= @path[-1] == "/" ? @path : @path + "/"
  10 + &nbsp;
  11 + = text_field_tag 'file_name', params[:file_name], placeholder: "sample.rb", required: true
  12 + %span
  13 + &nbsp;
  14 + on
  15 + %span.label-branch= @ref
  16 +
  17 + .control-group.commit_message-group
  18 + = label_tag 'commit_message', class: "control-label" do
  19 + Commit message
  20 + .controls
  21 + = text_area_tag 'commit_message', params[:commit_message], placeholder: "Added new file", required: true, rows: 3
  22 +
  23 + .file-holder
  24 + .file-title
  25 + %i.icon-file
  26 + .file-content.code
  27 + %pre#editor= params[:content]
  28 +
  29 + .form-actions
  30 + = hidden_field_tag 'content', '', id: "file-content"
  31 + .commit-button-annotation
  32 + = button_tag "Commit changes", class: 'btn commit-btn js-commit-button btn-create'
  33 + .message
  34 + to branch
  35 + %strong= @ref
  36 + = link_to "Cancel", project_tree_path(@project, @id), class: "btn btn-cancel", confirm: leave_edit_message
  37 +
  38 +:javascript
  39 + ace.config.set("modePath", gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}/ace-src-noconflict")
  40 + var editor = ace.edit("editor");
  41 +
  42 + disableButtonIfEmptyField("#commit_message", ".js-commit-button");
  43 +
  44 + $(".js-commit-button").click(function(){
  45 + $("#file-content").val(editor.getValue());
  46 + $(".file-editor form").submit();
  47 + });
app/views/projects/tree/_tree.html.haml
@@ -10,6 +10,12 @@ @@ -10,6 +10,12 @@
10 = link_to truncate(title, length: 40), project_tree_path(@project, path) 10 = link_to truncate(title, length: 40), project_tree_path(@project, path)
11 - else 11 - else
12 = link_to title, '#' 12 = link_to title, '#'
  13 + - if @repository.branch_names.include?(@ref)
  14 + \/
  15 + %li
  16 + = link_to project_new_tree_path(@project, @id), title: 'New file', id: 'new-file-link' do
  17 + %small
  18 + %i.icon-plus.light
13 19
14 %div#tree-content-holder.tree-content-holder 20 %div#tree-content-holder.tree-content-holder
15 %table#tree-slider{class: "table_#{@hex_path} tree-table" } 21 %table#tree-slider{class: "table_#{@hex_path} tree-table" }
config/routes.rb
@@ -166,16 +166,18 @@ Gitlab::Application.routes.draw do @@ -166,16 +166,18 @@ Gitlab::Application.routes.draw do
166 end 166 end
167 167
168 scope module: :projects do 168 scope module: :projects do
169 - resources :blob, only: [:show], constraints: {id: /.+/}  
170 - resources :raw, only: [:show], constraints: {id: /.+/}  
171 - resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ }  
172 - resources :edit_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'edit'  
173 - resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/}  
174 - resources :commits, only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}  
175 - resources :compare, only: [:index, :create]  
176 - resources :blame, only: [:show], constraints: {id: /.+/} 169 + resources :blob, only: [:show], constraints: {id: /.+/}
  170 + resources :raw, only: [:show], constraints: {id: /.+/}
  171 + resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ }
  172 + resources :edit_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'edit'
  173 + resources :new_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'new'
  174 + resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/}
  175 + resources :commits, only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}
  176 + resources :compare, only: [:index, :create]
  177 + resources :blame, only: [:show], constraints: {id: /.+/}
177 resources :network, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/} 178 resources :network, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/}
178 - resources :graphs, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/} 179 + resources :graphs, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/}
  180 +
179 match "/compare/:from...:to" => "compare#show", as: "compare", via: [:get, :post], constraints: {from: /.+/, to: /.+/} 181 match "/compare/:from...:to" => "compare#show", as: "compare", via: [:get, :post], constraints: {from: /.+/, to: /.+/}
180 182
181 resources :snippets, constraints: {id: /\d+/} do 183 resources :snippets, constraints: {id: /\d+/} do
features/project/source/browse_files.feature
@@ -20,6 +20,10 @@ Feature: Project Browse files @@ -20,6 +20,10 @@ Feature: Project Browse files
20 And I click link "raw" 20 And I click link "raw"
21 Then I should see raw file content 21 Then I should see raw file content
22 22
  23 + Scenario: I can create file
  24 + Given I click on "new file" link in repo
  25 + Then I can see new file page
  26 +
23 @javascript 27 @javascript
24 Scenario: I can edit file 28 Scenario: I can edit file
25 Given I click on "Gemfile.lock" file in repo 29 Given I click on "Gemfile.lock" file in repo
features/steps/project/project_browse_files.rb
@@ -3,42 +3,51 @@ class ProjectBrowseFiles &lt; Spinach::FeatureSteps @@ -3,42 +3,51 @@ class ProjectBrowseFiles &lt; Spinach::FeatureSteps
3 include SharedProject 3 include SharedProject
4 include SharedPaths 4 include SharedPaths
5 5
6 - Then 'I should see files from repository' do 6 + step 'I should see files from repository' do
7 page.should have_content "app" 7 page.should have_content "app"
8 page.should have_content "history" 8 page.should have_content "history"
9 page.should have_content "Gemfile" 9 page.should have_content "Gemfile"
10 end 10 end
11 11
12 - Then 'I should see files from repository for "8470d70"' do 12 + step 'I should see files from repository for "8470d70"' do
13 current_path.should == project_tree_path(@project, "8470d70") 13 current_path.should == project_tree_path(@project, "8470d70")
14 page.should have_content "app" 14 page.should have_content "app"
15 page.should have_content "history" 15 page.should have_content "history"
16 page.should have_content "Gemfile" 16 page.should have_content "Gemfile"
17 end 17 end
18 18
19 - Given 'I click on "Gemfile.lock" file in repo' do 19 + step 'I click on "Gemfile.lock" file in repo' do
20 click_link "Gemfile.lock" 20 click_link "Gemfile.lock"
21 end 21 end
22 22
23 - Then 'I should see it content' do 23 + step 'I should see it content' do
24 page.should have_content "DEPENDENCIES" 24 page.should have_content "DEPENDENCIES"
25 end 25 end
26 26
27 - And 'I click link "raw"' do 27 + step 'I click link "raw"' do
28 click_link "raw" 28 click_link "raw"
29 end 29 end
30 30
31 - Then 'I should see raw file content' do 31 + step 'I should see raw file content' do
32 page.source.should == ValidCommit::BLOB_FILE 32 page.source.should == ValidCommit::BLOB_FILE
33 end 33 end
34 34
35 - Given 'I click button "edit"' do 35 + step 'I click button "edit"' do
36 click_link 'edit' 36 click_link 'edit'
37 end 37 end
38 38
39 - Then 'I can edit code' do 39 + step 'I can edit code' do
40 page.execute_script('editor.setValue("GitlabFileEditor")') 40 page.execute_script('editor.setValue("GitlabFileEditor")')
41 page.evaluate_script('editor.getValue()').should == "GitlabFileEditor" 41 page.evaluate_script('editor.getValue()').should == "GitlabFileEditor"
42 end 42 end
43 43
  44 + step 'I click on "new file" link in repo' do
  45 + click_link 'new-file-link'
  46 + end
  47 +
  48 + step 'I can see new file page' do
  49 + page.should have_content "New file"
  50 + page.should have_content "File name"
  51 + page.should have_content "Commit message"
  52 + end
44 end 53 end
lib/gitlab/satellite/edit_file_action.rb
@@ -1,57 +0,0 @@ @@ -1,57 +0,0 @@
1 -module Gitlab  
2 - module Satellite  
3 - # GitLab server-side file update and commit  
4 - class EditFileAction < Action  
5 - attr_accessor :file_path, :ref  
6 -  
7 - def initialize(user, project, ref, file_path)  
8 - super user, project, git_timeout: 10.seconds  
9 - @file_path = file_path  
10 - @ref = ref  
11 - end  
12 -  
13 - # Updates the files content and creates a new commit for it  
14 - #  
15 - # Returns false if the ref has been updated while editing the file  
16 - # Returns false if committing the change fails  
17 - # Returns false if pushing from the satellite to Gitolite failed or was rejected  
18 - # Returns true otherwise  
19 - def commit!(content, commit_message, last_commit)  
20 - return false unless can_edit?(last_commit)  
21 -  
22 - in_locked_and_timed_satellite do |repo|  
23 - prepare_satellite!(repo)  
24 -  
25 - # create target branch in satellite at the corresponding commit from Gitolite  
26 - repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")  
27 -  
28 - # update the file in the satellite's working dir  
29 - file_path_in_satellite = File.join(repo.working_dir, file_path)  
30 - File.open(file_path_in_satellite, 'w') { |f| f.write(content) }  
31 -  
32 - # commit the changes  
33 - # will raise CommandFailed when commit fails  
34 - repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)  
35 -  
36 -  
37 - # push commit back to Gitolite  
38 - # will raise CommandFailed when push fails  
39 - repo.git.push({raise: true, timeout: true}, :origin, ref)  
40 -  
41 - # everything worked  
42 - true  
43 - end  
44 - rescue Grit::Git::CommandFailed => ex  
45 - Gitlab::GitLogger.error(ex.message)  
46 - false  
47 - end  
48 -  
49 - protected  
50 -  
51 - def can_edit?(last_commit)  
52 - current_last_commit = Gitlab::Git::Commit.last_for_path(@project.repository, ref, file_path).sha  
53 - last_commit == current_last_commit  
54 - end  
55 - end  
56 - end  
57 -end  
lib/gitlab/satellite/files/edit_file_action.rb 0 → 100644
@@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
  1 +require_relative 'file_action'
  2 +
  3 +module Gitlab
  4 + module Satellite
  5 + # GitLab server-side file update and commit
  6 + class EditFileAction < FileAction
  7 + # Updates the files content and creates a new commit for it
  8 + #
  9 + # Returns false if the ref has been updated while editing the file
  10 + # Returns false if committing the change fails
  11 + # Returns false if pushing from the satellite to Gitolite failed or was rejected
  12 + # Returns true otherwise
  13 + def commit!(content, commit_message, last_commit)
  14 + return false unless can_edit?(last_commit)
  15 +
  16 + in_locked_and_timed_satellite do |repo|
  17 + prepare_satellite!(repo)
  18 +
  19 + # create target branch in satellite at the corresponding commit from Gitolite
  20 + repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
  21 +
  22 + # update the file in the satellite's working dir
  23 + file_path_in_satellite = File.join(repo.working_dir, file_path)
  24 + File.open(file_path_in_satellite, 'w') { |f| f.write(content) }
  25 +
  26 + # commit the changes
  27 + # will raise CommandFailed when commit fails
  28 + repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
  29 +
  30 +
  31 + # push commit back to Gitolite
  32 + # will raise CommandFailed when push fails
  33 + repo.git.push({raise: true, timeout: true}, :origin, ref)
  34 +
  35 + # everything worked
  36 + true
  37 + end
  38 + rescue Grit::Git::CommandFailed => ex
  39 + Gitlab::GitLogger.error(ex.message)
  40 + false
  41 + end
  42 + end
  43 + end
  44 +end
lib/gitlab/satellite/files/file_action.rb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +module Gitlab
  2 + module Satellite
  3 + class FileAction < Action
  4 + attr_accessor :file_path, :ref
  5 +
  6 + def initialize(user, project, ref, file_path)
  7 + super user, project, git_timeout: 10.seconds
  8 + @file_path = file_path
  9 + @ref = ref
  10 + end
  11 +
  12 + protected
  13 +
  14 + def can_edit?(last_commit)
  15 + current_last_commit = Gitlab::Git::Commit.last_for_path(@project.repository, ref, file_path).sha
  16 + last_commit == current_last_commit
  17 + end
  18 + end
  19 + end
  20 +end
lib/gitlab/satellite/files/new_file_action.rb 0 → 100644
@@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
  1 +require_relative 'file_action'
  2 +
  3 +module Gitlab
  4 + module Satellite
  5 + class NewFileAction < FileAction
  6 + # Updates the files content and creates a new commit for it
  7 + #
  8 + # Returns false if the ref has been updated while editing the file
  9 + # Returns false if committing the change fails
  10 + # Returns false if pushing from the satellite to Gitolite failed or was rejected
  11 + # Returns true otherwise
  12 + def commit!(content, commit_message, file_name)
  13 + in_locked_and_timed_satellite do |repo|
  14 + prepare_satellite!(repo)
  15 +
  16 + # create target branch in satellite at the corresponding commit from Gitolite
  17 + repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
  18 +
  19 + # update the file in the satellite's working dir
  20 + file_path_in_satellite = File.join(repo.working_dir, file_path, file_name)
  21 + File.open(file_path_in_satellite, 'w') { |f| f.write(content) }
  22 +
  23 + # add new file
  24 + repo.add(file_path_in_satellite)
  25 +
  26 + # commit the changes
  27 + # will raise CommandFailed when commit fails
  28 + repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
  29 +
  30 +
  31 + # push commit back to Gitolite
  32 + # will raise CommandFailed when push fails
  33 + repo.git.push({raise: true, timeout: true}, :origin, ref)
  34 +
  35 + # everything worked
  36 + true
  37 + end
  38 + rescue Grit::Git::CommandFailed => ex
  39 + Gitlab::GitLogger.error(ex.message)
  40 + false
  41 + end
  42 + end
  43 + end
  44 +end