Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/projects/commit_controller.rb13
-rw-r--r--app/models/commit.rb8
-rw-r--r--app/models/repository.rb43
-rw-r--r--app/services/commits/revert_service.rb48
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