summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLuke "Jared" Bennett <lbennett@gitlab.com>2017-04-07 21:00:40 +0100
committerLuke "Jared" Bennett <lbennett@gitlab.com>2017-04-07 21:00:40 +0100
commit8b98ca50b3068fecc76233714fa7d363703ee55c (patch)
tree97d67331552de76faa9bfb8cec11616a369351fe /lib
parent501d403202d8b4f603dd1864790f56e85633b8ef (diff)
parentd37f1f1cd013a8b7a307e1004e020df086cba9d5 (diff)
downloadgitlab-ce-8b98ca50b3068fecc76233714fa7d363703ee55c.tar.gz
Merge branch 'master' into new-resolvable-discussion
Diffstat (limited to 'lib')
-rw-r--r--lib/api/entities.rb10
-rw-r--r--lib/gitlab/cache/ci/project_pipeline_status.rb103
-rw-r--r--lib/gitlab/checks/change_access.rb39
-rw-r--r--lib/gitlab/import_export/import_export.yml2
-rw-r--r--lib/gitlab/import_export/project_tree_restorer.rb6
-rw-r--r--lib/gitlab/import_export/relation_factory.rb1
-rw-r--r--lib/gitlab/user_access.rb20
-rw-r--r--lib/tasks/import.rake11
8 files changed, 169 insertions, 23 deletions
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 00d44821e3f..45625e00f7d 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -184,19 +184,15 @@ module API
end
expose :protected do |repo_branch, options|
- options[:project].protected_branch?(repo_branch.name)
+ ProtectedBranch.protected?(options[:project], repo_branch.name)
end
expose :developers_can_push do |repo_branch, options|
- project = options[:project]
- access_levels = project.protected_branches.matching(repo_branch.name).map(&:push_access_levels).flatten
- access_levels.any? { |access_level| access_level.access_level == Gitlab::Access::DEVELOPER }
+ options[:project].protected_branches.developers_can?(:push, repo_branch.name)
end
expose :developers_can_merge do |repo_branch, options|
- project = options[:project]
- access_levels = project.protected_branches.matching(repo_branch.name).map(&:merge_access_levels).flatten
- access_levels.any? { |access_level| access_level.access_level == Gitlab::Access::DEVELOPER }
+ options[:project].protected_branches.developers_can?(:merge, repo_branch.name)
end
end
diff --git a/lib/gitlab/cache/ci/project_pipeline_status.rb b/lib/gitlab/cache/ci/project_pipeline_status.rb
new file mode 100644
index 00000000000..b358f2efa4f
--- /dev/null
+++ b/lib/gitlab/cache/ci/project_pipeline_status.rb
@@ -0,0 +1,103 @@
+# This class is not backed by a table in the main database.
+# It loads the latest Pipeline for the HEAD of a repository, and caches that
+# in Redis.
+module Gitlab
+ module Cache
+ module Ci
+ class ProjectPipelineStatus
+ attr_accessor :sha, :status, :ref, :project, :loaded
+
+ delegate :commit, to: :project
+
+ def self.load_for_project(project)
+ new(project).tap do |status|
+ status.load_status
+ end
+ end
+
+ def self.update_for_pipeline(pipeline)
+ new(pipeline.project,
+ sha: pipeline.sha,
+ status: pipeline.status,
+ ref: pipeline.ref).store_in_cache_if_needed
+ end
+
+ def initialize(project, sha: nil, status: nil, ref: nil)
+ @project = project
+ @sha = sha
+ @ref = ref
+ @status = status
+ end
+
+ def has_status?
+ loaded? && sha.present? && status.present?
+ end
+
+ def load_status
+ return if loaded?
+
+ if has_cache?
+ load_from_cache
+ else
+ load_from_project
+ store_in_cache
+ end
+
+ self.loaded = true
+ end
+
+ def load_from_project
+ return unless commit
+
+ self.sha = commit.sha
+ self.status = commit.status
+ self.ref = project.default_branch
+ end
+
+ # We only cache the status for the HEAD commit of a project
+ # This status is rendered in project lists
+ def store_in_cache_if_needed
+ return delete_from_cache unless commit
+ return unless sha
+ return unless ref
+
+ if commit.sha == sha && project.default_branch == ref
+ store_in_cache
+ end
+ end
+
+ def load_from_cache
+ Gitlab::Redis.with do |redis|
+ self.sha, self.status, self.ref = redis.hmget(cache_key, :sha, :status, :ref)
+ end
+ end
+
+ def store_in_cache
+ Gitlab::Redis.with do |redis|
+ redis.mapped_hmset(cache_key, { sha: sha, status: status, ref: ref })
+ end
+ end
+
+ def delete_from_cache
+ Gitlab::Redis.with do |redis|
+ redis.del(cache_key)
+ end
+ end
+
+ def has_cache?
+ Gitlab::Redis.with do |redis|
+ redis.exists(cache_key)
+ end
+ end
+
+ def loaded?
+ self.loaded
+ end
+
+ def cache_key
+ "projects/#{project.id}/build_status"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb
index c85f79127bc..eb2f2e144fd 100644
--- a/lib/gitlab/checks/change_access.rb
+++ b/lib/gitlab/checks/change_access.rb
@@ -10,6 +10,7 @@ module Gitlab
)
@oldrev, @newrev, @ref = change.values_at(:oldrev, :newrev, :ref)
@branch_name = Gitlab::Git.branch_name(@ref)
+ @tag_name = Gitlab::Git.tag_name(@ref)
@user_access = user_access
@project = project
@env = env
@@ -32,11 +33,11 @@ module Gitlab
def protected_branch_checks
return if skip_authorization
return unless @branch_name
- return unless project.protected_branch?(@branch_name)
+ return unless ProtectedBranch.protected?(project, @branch_name)
if forced_push?
return "You are not allowed to force push code to a protected branch on this project."
- elsif Gitlab::Git.blank_ref?(@newrev)
+ elsif deletion?
return "You are not allowed to delete protected branches from this project."
end
@@ -58,13 +59,29 @@ module Gitlab
def tag_checks
return if skip_authorization
- tag_ref = Gitlab::Git.tag_name(@ref)
+ return unless @tag_name
- if tag_ref && protected_tag?(tag_ref) && user_access.cannot_do_action?(:admin_project)
- "You are not allowed to change existing tags on this project."
+ if tag_exists? && user_access.cannot_do_action?(:admin_project)
+ return "You are not allowed to change existing tags on this project."
+ end
+
+ protected_tag_checks
+ end
+
+ def protected_tag_checks
+ return unless tag_protected?
+ return "Protected tags cannot be updated." if update?
+ return "Protected tags cannot be deleted." if deletion?
+
+ unless user_access.can_create_tag?(@tag_name)
+ return "You are not allowed to create this tag as it is protected."
end
end
+ def tag_protected?
+ ProtectedTag.protected?(project, @tag_name)
+ end
+
def push_checks
return if skip_authorization
@@ -75,14 +92,22 @@ module Gitlab
private
- def protected_tag?(tag_name)
- project.repository.tag_exists?(tag_name)
+ def tag_exists?
+ project.repository.tag_exists?(@tag_name)
end
def forced_push?
Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev, env: @env)
end
+ def update?
+ !Gitlab::Git.blank_ref?(@oldrev) && !deletion?
+ end
+
+ def deletion?
+ Gitlab::Git.blank_ref?(@newrev)
+ end
+
def matching_merge_request?
Checks::MatchingMergeRequest.new(@newrev, @branch_name, @project).match?
end
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index f5e1e385ff9..899a6567768 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -47,6 +47,8 @@ project_tree:
- protected_branches:
- :merge_access_levels
- :push_access_levels
+ - protected_tags:
+ - :create_access_levels
- :project_feature
# Only include the following attributes for the models specified.
diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb
index df21ff22216..2e349b5f9a9 100644
--- a/lib/gitlab/import_export/project_tree_restorer.rb
+++ b/lib/gitlab/import_export/project_tree_restorer.rb
@@ -52,7 +52,11 @@ module Gitlab
create_sub_relations(relation, @tree_hash) if relation.is_a?(Hash)
relation_key = relation.is_a?(Hash) ? relation.keys.first : relation
- relation_hash = create_relation(relation_key, @tree_hash[relation_key.to_s])
+ relation_hash_list = @tree_hash[relation_key.to_s]
+
+ next unless relation_hash_list
+
+ relation_hash = create_relation(relation_key, relation_hash_list)
saved << restored_project.append_or_update_attribute(relation_key, relation_hash)
end
saved.all?
diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb
index 2ba12f5f924..71811be6f50 100644
--- a/lib/gitlab/import_export/relation_factory.rb
+++ b/lib/gitlab/import_export/relation_factory.rb
@@ -10,6 +10,7 @@ module Gitlab
hooks: 'ProjectHook',
merge_access_levels: 'ProtectedBranch::MergeAccessLevel',
push_access_levels: 'ProtectedBranch::PushAccessLevel',
+ create_access_levels: 'ProtectedTag::CreateAccessLevel',
labels: :project_labels,
priorities: :label_priorities,
label: :project_label }.freeze
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index f260c0c535f..54728e5ff0e 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -28,14 +28,23 @@ module Gitlab
true
end
+ def can_create_tag?(ref)
+ return false unless can_access_git?
+
+ if ProtectedTag.protected?(project, ref)
+ project.protected_tags.protected_ref_accessible_to?(ref, user, action: :create)
+ else
+ user.can?(:push_code, project)
+ end
+ end
+
def can_push_to_branch?(ref)
return false unless can_access_git?
- if project.protected_branch?(ref)
+ if ProtectedBranch.protected?(project, ref)
return true if project.empty_repo? && project.user_can_push_to_empty_repo?(user)
- access_levels = project.protected_branches.matching(ref).map(&:push_access_levels).flatten
- has_access = access_levels.any? { |access_level| access_level.check_access(user) }
+ has_access = project.protected_branches.protected_ref_accessible_to?(ref, user, action: :push)
has_access || !project.repository.branch_exists?(ref) && can_merge_to_branch?(ref)
else
@@ -46,9 +55,8 @@ module Gitlab
def can_merge_to_branch?(ref)
return false unless can_access_git?
- if project.protected_branch?(ref)
- access_levels = project.protected_branches.matching(ref).map(&:merge_access_levels).flatten
- access_levels.any? { |access_level| access_level.check_access(user) }
+ if ProtectedBranch.protected?(project, ref)
+ project.protected_branches.protected_ref_accessible_to?(ref, user, action: :merge)
else
user.can?(:push_code, project)
end
diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake
index 350afeb5c0b..15131fbf755 100644
--- a/lib/tasks/import.rake
+++ b/lib/tasks/import.rake
@@ -48,9 +48,16 @@ class NewImporter < ::Gitlab::GithubImport::Importer
begin
raise 'Blocked import URL.' if Gitlab::UrlBlocker.blocked_url?(project.import_url)
- gitlab_shell.import_repository(project.repository_storage_path, project.path_with_namespace, project.import_url)
+ project.create_repository
+ project.repository.add_remote(project.import_type, project.import_url)
+ project.repository.set_remote_as_mirror(project.import_type)
+ project.repository.fetch_remote(project.import_type, forced: true)
+ project.repository.remove_remote(project.import_type)
rescue => e
- project.repository.before_import if project.repository_exists?
+ # Expire cache to prevent scenarios such as:
+ # 1. First import failed, but the repo was imported successfully, so +exists?+ returns true
+ # 2. Retried import, repo is broken or not imported but +exists?+ still returns true
+ project.repository.expire_content_cache if project.repository_exists?
raise "Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}"
end