Commit 80613993 authored by Rubén Dávila's avatar Rubén Dávila Committed by Robert Speicher

Add RevertService class with basic logic to revert commit

parent 34e26b82
...@@ -11,6 +11,7 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -11,6 +11,7 @@ class Projects::CommitController < Projects::ApplicationController
before_action :authorize_read_commit_status!, only: [:builds] before_action :authorize_read_commit_status!, only: [:builds]
before_action :commit before_action :commit
before_action :define_show_vars, only: [:show, :builds] before_action :define_show_vars, only: [:show, :builds]
before_action :assign_revert_commit_vars, only: [:revert]
before_action :authorize_edit_tree!, only: [:revert] before_action :authorize_edit_tree!, only: [:revert]
def show def show
...@@ -59,7 +60,11 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -59,7 +60,11 @@ class Projects::CommitController < Projects::ApplicationController
end end
def revert def revert
# return render_404 unless @commit_params.values.all?
create_commit(Commits::RevertService, success_notice: "The commit has been successfully reverted.",
success_path: namespace_project_commits_path(@project.namespace, @project, @target_branch),
failure_path: namespace_project_commit_path(@project.namespace, @project, params[:id]))
end end
private private
...@@ -86,4 +91,12 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -86,4 +91,12 @@ class Projects::CommitController < Projects::ApplicationController
@statuses = ci_commit.statuses if ci_commit @statuses = ci_commit.statuses if ci_commit
end end
def assign_revert_commit_vars
@target_branch = params[:target_branch]
@commit_params = {
revert_commit_id: params[:id],
}
end
end end
...@@ -215,6 +215,14 @@ class Commit ...@@ -215,6 +215,14 @@ class Commit
ci_commit.try(:status) || :not_found ci_commit.try(:status) || :not_found
end end
def revert_branch_name
"revert-#{project.id}-#{short_id}"
end
def revert_message
"Revert \"#{safe_message.lines.first}\"".truncate(80) + "\n\nReverts #{to_reference}"
end
private private
def repo_changes def repo_changes
......
...@@ -622,29 +622,48 @@ class Repository ...@@ -622,29 +622,48 @@ class Repository
merge_commit_sha merge_commit_sha
end end
def revert_merge(user, merge_commit_id, new_branch_name, target_branch, commit_message) def revert(user, commit_id, target_branch, base_branch, commit_message)
# branch exists and it's highly probable that it has the revert commit source_sha = find_branch(base_branch).target
return if find_branch(new_branch_name) target_sha = find_branch(target_branch).try(:target)
target_sha = find_branch(target_branch).target # First make revert in temp branch
unless target_sha
revert_commit(user, commit_id, target_branch, base_branch, commit_message)
end
commit_with_hooks(user, new_branch_name) do |ref| # Make the revert happen in the target branch
new_index = rugged.revert_commit(merge_commit_id, target_sha, mainline: 1) source_sha = find_branch(target_branch).target
committer = user_to_committer(user) target_sha = find_branch(base_branch).target
if is_there_something_to_merge?(source_sha, target_sha)
revert_commit(user, commit_id, base_branch, base_branch, commit_message)
end
end
def revert_commit(user, commit_id, target_branch, base_branch, commit_message)
base_sha = find_branch(base_branch).target
commit_with_hooks(user, target_branch) do |ref|
new_index = rugged.revert_commit(commit_id, base_sha)#, mainline: 1)
return false if new_index.conflicts?
options = { committer = user_to_committer(user)
source_sha = Rugged::Commit.create(rugged, {
message: commit_message, message: commit_message,
author: committer, author: committer,
committer: committer, committer: committer,
tree: new_index.write_tree(rugged), tree: new_index.write_tree(rugged),
parents: [rugged.lookup(target_sha)], parents: [rugged.lookup(base_sha)],
update_ref: ref update_ref: ref
} })
Rugged::Commit.create(rugged, options)
end end
end end
def is_there_something_to_merge?(source_branch_sha, target_branch_sha)
CompareService.new.execute(project, source_branch_sha, project, target_branch_sha).diffs.present?
end
def merged_to_root_ref?(branch_name) def merged_to_root_ref?(branch_name)
branch_commit = commit(branch_name) branch_commit = commit(branch_name)
root_ref_commit = commit(root_ref) root_ref_commit = commit(root_ref)
......
module Commits
class RevertService < ::BaseService
class ValidationError < StandardError; end
def execute
@source_project = params[:source_project] || @project
@target_branch = params[:target_branch]
@commit_to_revert = @source_project.commit(params[:revert_commit_id])
# Check push permissions to branch
validate
if commit
success
else
error("Something went wrong. Your changes were not committed")
end
rescue Repository::CommitError, Gitlab::Git::Repository::InvalidBlobName, GitHooksService::PreReceiveError, ValidationError => ex
error(ex.message)
end
def commit
raw_repo = repository.rugged
# Create branch with revert commit
reverted = repository.revert(current_user, @commit_to_revert.id,
@commit_to_revert.revert_branch_name, @target_branch,
@commit_to_revert.revert_message)
repository.rm_branch(current_user, @commit_to_revert.revert_branch_name)
reverted
end
private
def raise_error(message)
raise ValidationError.new(message)
end
def validate
allowed = ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(@target_branch)
unless allowed
raise_error("You are not allowed to push into this branch")
end
end
end
end
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