69 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			69 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| require_relative 'file_action'
 | |
| 
 | |
| module Gitlab
 | |
|   module Satellite
 | |
|     # GitLab server-side file update and commit
 | |
|     class EditFileAction < FileAction
 | |
|       # Updates the files content and creates a new commit for it
 | |
|       #
 | |
|       # Returns false if the ref has been updated while editing the file
 | |
|       # Returns false if committing the change fails
 | |
|       # Returns false if pushing from the satellite to bare repo failed or was rejected
 | |
|       # Returns true otherwise
 | |
|       def commit!(content, commit_message, encoding, new_branch = nil)
 | |
|         in_locked_and_timed_satellite do |repo|
 | |
|           prepare_satellite!(repo)
 | |
| 
 | |
|           # create target branch in satellite at the corresponding commit from bare repo
 | |
|           begin
 | |
|             repo.git.checkout({ raise: true, timeout: true, b: true }, ref, "origin/#{ref}")
 | |
|           rescue Grit::Git::CommandFailed => ex
 | |
|             log_and_raise(CheckoutFailed, ex.message)
 | |
|           end
 | |
| 
 | |
|           # update the file in the satellite's working dir
 | |
|           file_path_in_satellite = File.join(repo.working_dir, file_path)
 | |
| 
 | |
|           # Prevent relative links
 | |
|           unless safe_path?(file_path_in_satellite)
 | |
|             Gitlab::GitLogger.error("FileAction: Relative path not allowed")
 | |
|             return false
 | |
|           end
 | |
| 
 | |
|           # Write file
 | |
|           write_file(file_path_in_satellite, content, encoding)
 | |
| 
 | |
|           # commit the changes
 | |
|           # will raise CommandFailed when commit fails
 | |
|           begin
 | |
|             repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
 | |
|           rescue Grit::Git::CommandFailed => ex
 | |
|             log_and_raise(CommitFailed, ex.message)
 | |
|           end
 | |
| 
 | |
| 
 | |
|           target_branch = new_branch.present? ? "#{ref}:#{new_branch}" : ref
 | |
| 
 | |
|           # push commit back to bare repo
 | |
|           # will raise CommandFailed when push fails
 | |
|           begin
 | |
|             repo.git.push({ raise: true, timeout: true }, :origin, target_branch)
 | |
|           rescue Grit::Git::CommandFailed => ex
 | |
|             log_and_raise(PushFailed, ex.message)
 | |
|           end
 | |
| 
 | |
|           # everything worked
 | |
|           true
 | |
|         end
 | |
|       end
 | |
| 
 | |
|       private
 | |
| 
 | |
|       def log_and_raise(errorClass, message)
 | |
|         Gitlab::GitLogger.error(message)
 | |
|         raise(errorClass, message)
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| end
 |