diff options
author | Rubén Dávila <rdavila84@gmail.com> | 2016-02-03 18:28:40 -0500 |
---|---|---|
committer | Robert Speicher <rspeicher@gmail.com> | 2016-02-19 13:14:50 -0500 |
commit | 806139936898726b32c4fe216ac3a9f4419ce91e (patch) | |
tree | 7329f75325b00fe74999ed1d5d384c9ff01038d3 /app | |
parent | 34e26b8212954dba32165c39b63858658b82c0f0 (diff) | |
download | gitlab-ce-806139936898726b32c4fe216ac3a9f4419ce91e.tar.gz |
Add RevertService class with basic logic to revert commit
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/projects/commit_controller.rb | 13 | ||||
-rw-r--r-- | app/models/commit.rb | 8 | ||||
-rw-r--r-- | app/models/repository.rb | 43 | ||||
-rw-r--r-- | app/services/commits/revert_service.rb | 48 |
4 files changed, 100 insertions, 12 deletions
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 96cb9761f3b..d996b0f4ca7 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -11,6 +11,7 @@ class Projects::CommitController < Projects::ApplicationController before_action :authorize_read_commit_status!, only: [:builds] before_action :commit before_action :define_show_vars, only: [:show, :builds] + before_action :assign_revert_commit_vars, only: [:revert] before_action :authorize_edit_tree!, only: [:revert] def show @@ -59,7 +60,11 @@ class Projects::CommitController < Projects::ApplicationController end 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 private @@ -86,4 +91,12 @@ class Projects::CommitController < Projects::ApplicationController @statuses = ci_commit.statuses if ci_commit end + + def assign_revert_commit_vars + @target_branch = params[:target_branch] + + @commit_params = { + revert_commit_id: params[:id], + } + end end diff --git a/app/models/commit.rb b/app/models/commit.rb index 23b771aebb7..e05bddc24c6 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -215,6 +215,14 @@ class Commit ci_commit.try(:status) || :not_found 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 def repo_changes diff --git a/app/models/repository.rb b/app/models/repository.rb index cca7afadbec..19d898c85ea 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -622,29 +622,48 @@ class Repository merge_commit_sha end - def revert_merge(user, merge_commit_id, new_branch_name, target_branch, commit_message) - # branch exists and it's highly probable that it has the revert commit - return if find_branch(new_branch_name) + def revert(user, commit_id, target_branch, base_branch, commit_message) + source_sha = find_branch(base_branch).target + 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| - new_index = rugged.revert_commit(merge_commit_id, target_sha, mainline: 1) - committer = user_to_committer(user) + # Make the revert happen in the target branch + source_sha = find_branch(target_branch).target + 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, author: committer, committer: committer, tree: new_index.write_tree(rugged), - parents: [rugged.lookup(target_sha)], + parents: [rugged.lookup(base_sha)], update_ref: ref - } - - Rugged::Commit.create(rugged, options) + }) 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) branch_commit = commit(branch_name) root_ref_commit = commit(root_ref) diff --git a/app/services/commits/revert_service.rb b/app/services/commits/revert_service.rb new file mode 100644 index 00000000000..4a364f0d86a --- /dev/null +++ b/app/services/commits/revert_service.rb @@ -0,0 +1,48 @@ +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 |