Commit 3a3c4ea4 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'gitlab-shell-2-0' into 'master'

Modify GitLab to work with gitlab-shell 2.0

Related to #1516

See merge request !1057
parents 7e7f5286 7f99aa57
1.9.7 2.0.0
...@@ -4,8 +4,7 @@ class PostReceive ...@@ -4,8 +4,7 @@ class PostReceive
sidekiq_options queue: :post_receive sidekiq_options queue: :post_receive
def perform(repo_path, oldrev, newrev, ref, identifier) def perform(repo_path, identifier, changes)
if repo_path.start_with?(Gitlab.config.gitlab_shell.repos_path.to_s) if repo_path.start_with?(Gitlab.config.gitlab_shell.repos_path.to_s)
repo_path.gsub!(Gitlab.config.gitlab_shell.repos_path.to_s, "") repo_path.gsub!(Gitlab.config.gitlab_shell.repos_path.to_s, "")
else else
...@@ -22,17 +21,23 @@ class PostReceive ...@@ -22,17 +21,23 @@ class PostReceive
return false return false
end end
user = identify(identifier, project, newrev) changes = changes.lines if changes.kind_of?(String)
changes.each do |change|
oldrev, newrev, ref = change.strip.split(' ')
unless user @user ||= identify(identifier, project, newrev)
unless @user
log("Triggered hook for non-existing user \"#{identifier} \"") log("Triggered hook for non-existing user \"#{identifier} \"")
return false return false
end end
if tag?(ref) if tag?(ref)
GitTagPushService.new.execute(project, user, oldrev, newrev, ref) GitTagPushService.new.execute(project, @user, oldrev, newrev, ref)
else else
GitPushService.new.execute(project, user, oldrev, newrev, ref) GitPushService.new.execute(project, @user, oldrev, newrev, ref)
end
end end
end end
......
...@@ -34,10 +34,7 @@ module API ...@@ -34,10 +34,7 @@ module API
actor, actor,
params[:action], params[:action],
project, project,
params[:ref], params[:changes]
params[:oldrev],
params[:newrev],
params[:forced_push]
) )
end end
......
...@@ -5,7 +5,7 @@ module Gitlab ...@@ -5,7 +5,7 @@ module Gitlab
attr_reader :params, :project, :git_cmd, :user attr_reader :params, :project, :git_cmd, :user
def allowed?(actor, cmd, project, ref = nil, oldrev = nil, newrev = nil, forced_push = false) def allowed?(actor, cmd, project, changes = nil)
case cmd case cmd
when *DOWNLOAD_COMMANDS when *DOWNLOAD_COMMANDS
if actor.is_a? User if actor.is_a? User
...@@ -19,12 +19,12 @@ module Gitlab ...@@ -19,12 +19,12 @@ module Gitlab
end end
when *PUSH_COMMANDS when *PUSH_COMMANDS
if actor.is_a? User if actor.is_a? User
push_allowed?(actor, project, ref, oldrev, newrev, forced_push) push_allowed?(actor, project, changes)
elsif actor.is_a? DeployKey elsif actor.is_a? DeployKey
# Deploy key not allowed to push # Deploy key not allowed to push
return false return false
elsif actor.is_a? Key elsif actor.is_a? Key
push_allowed?(actor.user, project, ref, oldrev, newrev, forced_push) push_allowed?(actor.user, project, changes)
else else
raise 'Wrong actor' raise 'Wrong actor'
end end
...@@ -41,11 +41,19 @@ module Gitlab ...@@ -41,11 +41,19 @@ module Gitlab
end end
end end
def push_allowed?(user, project, ref, oldrev, newrev, forced_push) def push_allowed?(user, project, changes)
if user && user_allowed?(user) return false unless user && user_allowed?(user)
return true if changes.blank?
changes = changes.lines if changes.kind_of?(String)
# Iterate over all changes to find if user allowed all of them to be applied
changes.each do |change|
oldrev, newrev, ref = changes.split('')
action = if project.protected_branch?(ref) action = if project.protected_branch?(ref)
# we dont allow force push to protected branch # we dont allow force push to protected branch
if forced_push.to_s == 'true' if forced_push?(oldrev, newrev)
:force_push_code_to_protected_branches :force_push_code_to_protected_branches
# and we dont allow remove of protected branch # and we dont allow remove of protected branch
elsif newrev =~ /0000000/ elsif newrev =~ /0000000/
...@@ -59,7 +67,22 @@ module Gitlab ...@@ -59,7 +67,22 @@ module Gitlab
else else
:push_code :push_code
end end
user.can?(action, project) unless user.can?(action, project)
# If user does not have access to make at least one change - cancel all push
return false
end
end
# If user has access to make all changes
true
end
def forced_push?(oldrev, newrev)
return false if project.empty_repo?
if oldrev !~ /00000000/ && newrev !~ /00000000/
missed_refs = IO.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})).read
missed_refs.split("\n").size > 0
else else
false false
end end
......
...@@ -157,7 +157,6 @@ describe API::API, api: true do ...@@ -157,7 +157,6 @@ describe API::API, api: true do
def pull(key, project) def pull(key, project)
get( get(
api("/internal/allowed"), api("/internal/allowed"),
ref: 'master',
key_id: key.id, key_id: key.id,
project: project.path_with_namespace, project: project.path_with_namespace,
action: 'git-upload-pack' action: 'git-upload-pack'
...@@ -167,7 +166,7 @@ describe API::API, api: true do ...@@ -167,7 +166,7 @@ describe API::API, api: true do
def push(key, project) def push(key, project)
get( get(
api("/internal/allowed"), api("/internal/allowed"),
ref: 'master', changes: 'd14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master',
key_id: key.id, key_id: key.id,
project: project.path_with_namespace, project: project.path_with_namespace,
action: 'git-receive-pack' action: 'git-receive-pack'
......
require 'spec_helper' require 'spec_helper'
describe PostReceive do describe PostReceive do
context "as a resque worker" do context "as a resque worker" do
it "reponds to #perform" do it "reponds to #perform" do
PostReceive.new.should respond_to(:perform) PostReceive.new.should respond_to(:perform)
...@@ -15,7 +14,7 @@ describe PostReceive do ...@@ -15,7 +14,7 @@ describe PostReceive do
it "fetches the correct project" do it "fetches the correct project" do
Project.should_receive(:find_with_namespace).with(project.path_with_namespace).and_return(project) Project.should_receive(:find_with_namespace).with(project.path_with_namespace).and_return(project)
PostReceive.new.perform(pwd(project), 'sha-old', 'sha-new', 'refs/heads/master', key_id) PostReceive.new.perform(pwd(project), key_id, changes)
end end
it "does not run if the author is not in the project" do it "does not run if the author is not in the project" do
...@@ -23,7 +22,7 @@ describe PostReceive do ...@@ -23,7 +22,7 @@ describe PostReceive do
project.should_not_receive(:execute_hooks) project.should_not_receive(:execute_hooks)
PostReceive.new.perform(pwd(project), 'sha-old', 'sha-new', 'refs/heads/master', key_id).should be_false PostReceive.new.perform(pwd(project), key_id, changes).should be_false
end end
it "asks the project to trigger all hooks" do it "asks the project to trigger all hooks" do
...@@ -32,11 +31,15 @@ describe PostReceive do ...@@ -32,11 +31,15 @@ describe PostReceive do
project.should_receive(:execute_services) project.should_receive(:execute_services)
project.should_receive(:update_merge_requests) project.should_receive(:update_merge_requests)
PostReceive.new.perform(pwd(project), 'sha-old', 'sha-new', 'refs/heads/master', key_id) PostReceive.new.perform(pwd(project), key_id, changes)
end end
end end
def pwd(project) def pwd(project)
File.join(Gitlab.config.gitlab_shell.repos_path, project.path_with_namespace) File.join(Gitlab.config.gitlab_shell.repos_path, project.path_with_namespace)
end end
def changes
'd14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master'
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