diff options
author | Luke "Jared" Bennett <lbennett@gitlab.com> | 2017-04-07 21:00:40 +0100 |
---|---|---|
committer | Luke "Jared" Bennett <lbennett@gitlab.com> | 2017-04-07 21:00:40 +0100 |
commit | 8b98ca50b3068fecc76233714fa7d363703ee55c (patch) | |
tree | 97d67331552de76faa9bfb8cec11616a369351fe /lib | |
parent | 501d403202d8b4f603dd1864790f56e85633b8ef (diff) | |
parent | d37f1f1cd013a8b7a307e1004e020df086cba9d5 (diff) | |
download | gitlab-ce-8b98ca50b3068fecc76233714fa7d363703ee55c.tar.gz |
Merge branch 'master' into new-resolvable-discussion
Diffstat (limited to 'lib')
-rw-r--r-- | lib/api/entities.rb | 10 | ||||
-rw-r--r-- | lib/gitlab/cache/ci/project_pipeline_status.rb | 103 | ||||
-rw-r--r-- | lib/gitlab/checks/change_access.rb | 39 | ||||
-rw-r--r-- | lib/gitlab/import_export/import_export.yml | 2 | ||||
-rw-r--r-- | lib/gitlab/import_export/project_tree_restorer.rb | 6 | ||||
-rw-r--r-- | lib/gitlab/import_export/relation_factory.rb | 1 | ||||
-rw-r--r-- | lib/gitlab/user_access.rb | 20 | ||||
-rw-r--r-- | lib/tasks/import.rake | 11 |
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 |