Class: Project
- Inherits:
-
ApplicationRecord
show all
- Extended by:
- Gitlab::Cache::RequestCache, Gitlab::ConfigHelper
- Includes:
- AccessRequestable, AfterCommitQueue, Avatarable, BatchDestroyDependentAssociations, CacheMarkdownField, CaseSensitivity, ChronicDurationAttribute, DeploymentPlatform, FastDestroyAll::Helpers, FeatureGate, FromUnion, Gitlab::ConfigHelper, Gitlab::SQL::Pattern, Gitlab::Utils::StrongMemoize, Gitlab::VisibilityLevel, GroupDescendant, HasRepository, HasWiki, IgnorableColumns, Integration, OptionallySearch, Presentable, ProjectAPICompatibility, ProjectFeaturesCompatibility, Routable, SelectForProjectAuthorization, Sortable, TokenAuthenticatable, ValidAttribute, WithUploads
- Defined in:
- app/models/project.rb
Constant Summary
collapse
- BoardLimitExceeded =
Class.new(StandardError)
- STATISTICS_ATTRIBUTE =
'repositories_count'
- UNKNOWN_IMPORT_URL =
'http://unknown.git'
- LATEST_STORAGE_VERSION =
Hashed Storage versions handle rolling out new storage to project and dependents models: nil: legacy 1: repository 2: attachments
2
- HASHED_STORAGE_FEATURES =
{
repository: 1,
attachments: 2
}.freeze
- VALID_IMPORT_PORTS =
[80, 443].freeze
- VALID_IMPORT_PROTOCOLS =
%w(http https git).freeze
- VALID_MIRROR_PORTS =
[22, 80, 443].freeze
- VALID_MIRROR_PROTOCOLS =
%w(http https ssh git).freeze
- ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT =
10
- SORTING_PREFERENCE_FIELD =
:projects_sort
- MAX_BUILD_TIMEOUT =
1.month
BatchDestroyDependentAssociations::DEPENDENT_ASSOCIATIONS_BATCH_SIZE
Constants included
from WithUploads
WithUploads::FILE_UPLOADERS
Gitlab::SQL::Pattern::MIN_CHARS_FOR_PARTIAL_MATCHING, Gitlab::SQL::Pattern::REGEX_QUOTED_WORD
CacheMarkdownField::INVALIDATED_BY
Constants included
from Avatarable
Avatarable::ALLOWED_IMAGE_SCALER_WIDTHS
Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::PUBLIC
Instance Attribute Summary collapse
#request_cache_key_block
Class Method Summary
collapse
Instance Method Summary
collapse
-
#access_request_approvers_to_be_notified ⇒ Object
-
#active_runners ⇒ Object
-
#active_webide_pipelines(user:) ⇒ Object
-
#add_export_job(current_user:, after_export_strategy: nil, params: {}) ⇒ Object
-
#add_import_job ⇒ Object
-
#after_create_default_branch ⇒ Object
rubocop: disable CodeReuse/ServiceClass.
-
#after_import ⇒ Object
-
#alerts_service_activated? ⇒ Boolean
-
#all_clusters ⇒ Object
-
#all_lfs_objects ⇒ Object
This will return all `lfs_objects` that are accessible to the project and the fork source.
-
#all_lfs_objects_oids(oids: []) ⇒ Object
TODO: Remove this method once all LfsObjectsProject records are backfilled for forks.
-
#all_pipelines ⇒ Object
-
#all_runners ⇒ Object
-
#allowed_to_share_with_group? ⇒ Boolean
-
#ancestors_upto(top = nil, hierarchy_order: nil) ⇒ Object
(also: #ancestors)
returns all ancestor-groups upto but excluding the given namespace when no namespace is given, all ancestors upto the top are returned.
-
#any_branch_allows_collaboration?(user) ⇒ Boolean
-
#any_lfs_file_locks? ⇒ Boolean
-
#any_runners?(&block) ⇒ Boolean
-
#api_variables ⇒ Object
-
#auto_cancel_pending_pipelines? ⇒ Boolean
-
#auto_devops_enabled? ⇒ Boolean
-
#auto_devops_variables ⇒ Object
-
#autoclose_referenced_issues ⇒ Object
-
#avatar_in_git ⇒ Object
-
#avatar_url(**args) ⇒ Object
-
#badges ⇒ Object
-
#bare_repository_import? ⇒ Boolean
-
#bots ⇒ Object
-
#branch_allows_collaboration?(user, branch_name) ⇒ Boolean
-
#build_commit_note(commit) ⇒ Object
-
#cache_has_external_issue_tracker ⇒ Object
-
#cache_has_external_wiki ⇒ Object
-
#change_head(branch) ⇒ Object
-
#check_personal_projects_limit ⇒ Object
-
#check_repository_path_availability ⇒ Object
Check if repository already exists on disk.
-
#ci_config_path=(value) ⇒ Object
-
#ci_config_path_or_default ⇒ Object
-
#ci_instance_variables_for(ref:) ⇒ Object
-
#ci_pipelines ⇒ Object
-
#ci_service ⇒ Object
-
#ci_services ⇒ Object
rubocop: enable CodeReuse/ServiceClass.
-
#ci_variables_for(ref:, environment: nil) ⇒ Object
-
#cleanup ⇒ Object
(also: #reload_repository!)
-
#closest_setting(name) ⇒ Object
-
#code ⇒ Object
For compatibility with old code.
-
#container_registry_url ⇒ Object
-
#container_registry_variables ⇒ Object
-
#context_commits_enabled? ⇒ Boolean
-
#create_labels ⇒ Object
rubocop: disable CodeReuse/ServiceClass.
-
#create_or_update_import_data(data: nil, credentials: nil) ⇒ Object
-
#create_repository(force: false) ⇒ Object
-
#default_branch_or_master ⇒ Object
-
#default_branch_protected? ⇒ Boolean
-
#default_environment ⇒ Object
-
#default_issues_tracker? ⇒ Boolean
-
#default_merge_request_target ⇒ Object
-
#default_owner ⇒ Object
-
#deploy_token_create_url(opts = {}) ⇒ Object
-
#deploy_token_revoke_url_for(token) ⇒ Object
-
#deployment_variables(environment:, kubernetes_namespace: nil) ⇒ Object
-
#design_management_enabled? ⇒ Boolean
LFS and hashed repository storage are required for using Design Management.
-
#design_repository ⇒ Object
-
#disabled_services ⇒ Object
-
#drop_visibility_level! ⇒ Object
-
#emails_disabled? ⇒ Boolean
-
#enable_ci ⇒ Object
-
#enabled_group_deploy_keys ⇒ Object
-
#ensure_repository ⇒ Object
-
#environments_for_scope(scope) ⇒ Object
-
#execute_hooks(data, hooks_scope = :push_hooks) ⇒ Object
rubocop: disable CodeReuse/ServiceClass.
-
#execute_services(data, hooks_scope = :push_hooks) ⇒ Object
rubocop: enable CodeReuse/ServiceClass.
-
#expire_caches_before_rename(old_path) ⇒ Object
Expires various caches before a project is renamed.
-
#export_enqueued? ⇒ Boolean
-
#export_file ⇒ Object
-
#export_file_exists? ⇒ Boolean
-
#export_in_progress? ⇒ Boolean
-
#export_path ⇒ Object
-
#export_status ⇒ Object
-
#external_authorization_classification_label ⇒ Object
-
#external_import? ⇒ Boolean
-
#external_issue_reference_pattern ⇒ Object
-
#external_issue_tracker ⇒ Object
-
#external_references_supported? ⇒ Boolean
-
#external_wiki ⇒ Object
-
#feature_usage ⇒ Object
-
#ff_merge_must_be_possible? ⇒ Boolean
-
#find_or_initialize_service(name) ⇒ Object
-
#find_or_initialize_services ⇒ Object
-
#first_auto_devops_config ⇒ Object
-
#fork_source ⇒ Object
-
#forked? ⇒ Boolean
-
#forked_from?(other_project) ⇒ Boolean
-
#forks_count ⇒ Object
rubocop: disable CodeReuse/ServiceClass.
-
#full_path_before_last_save ⇒ Object
-
#full_path_slug ⇒ Object
-
#get_issue(issue_id, current_user) ⇒ Object
-
#git_objects_poolable? ⇒ Boolean
Git objects are only poolable when the project is or has: - Hashed storage -> The object pool will have a remote to its members, using relative paths.
-
#git_transfer_in_progress? ⇒ Boolean
-
#gitea_import? ⇒ Boolean
-
#gitlab_deploy_token ⇒ Object
-
#gitlab_project_import? ⇒ Boolean
-
#group_runners ⇒ Object
-
#has_active_hooks?(hooks_scope = :push_hooks) ⇒ Boolean
-
#has_active_services?(hooks_scope = :push_hooks) ⇒ Boolean
-
#has_auto_devops_implicitly_disabled? ⇒ Boolean
-
#has_auto_devops_implicitly_enabled? ⇒ Boolean
-
#has_ci? ⇒ Boolean
-
#has_container_registry_tags? ⇒ Boolean
-
#has_packages?(package_type) ⇒ Boolean
-
#has_pool_repository? ⇒ Boolean
-
#has_remote_mirror? ⇒ Boolean
-
#has_wiki? ⇒ Boolean
-
#hashed_storage?(feature) ⇒ Boolean
Check if Hashed Storage is enabled for the project with at least informed feature rolled out.
-
#hook_attrs(backward: true) ⇒ Object
-
#human_import_status_name ⇒ Object
-
#human_merge_method ⇒ Object
-
#import? ⇒ Boolean
-
#import_export_shared ⇒ Object
-
#import_status ⇒ Object
-
#import_url ⇒ Object
-
#import_url=(value) ⇒ Object
-
#in_fork_network_of?(other_project) ⇒ Boolean
-
#increment_pushes_since_gc ⇒ Object
-
#initialize(attributes = nil) ⇒ Project
constructor
A new instance of Project.
-
#issue_exists?(issue_id) ⇒ Boolean
-
#items_for(entity) ⇒ Object
-
#jira_import? ⇒ Boolean
-
#jira_import_status ⇒ Object
-
#jira_subscription_exists? ⇒ Boolean
-
#last_activity ⇒ Object
-
#last_activity_date ⇒ Object
-
#latest_jira_import ⇒ Object
-
#latest_pipeline(ref = default_branch, sha = nil) ⇒ Object
-
#latest_successful_build_for_ref(job_name, ref = default_branch) ⇒ Object
ref can't be HEAD, can only be branch/tag name.
-
#latest_successful_build_for_ref!(job_name, ref = default_branch) ⇒ Object
-
#latest_successful_build_for_sha(job_name, sha) ⇒ Object
-
#latest_successful_pipeline_for(ref = nil) ⇒ Object
-
#latest_successful_pipeline_for_default_branch ⇒ Object
-
#leave_pool_repository ⇒ Object
-
#legacy_storage? ⇒ Boolean
rubocop: enable CodeReuse/ServiceClass.
-
#lfs_enabled? ⇒ Boolean
(also: #lfs_enabled)
-
#lfs_http_url_to_repo(_) ⇒ Object
-
#lfs_objects_oids(oids: []) ⇒ Object
-
#lfs_storage_project ⇒ Object
TODO: Remove this method once all LfsObjectsProject records are backfilled for forks.
-
#licensed_features ⇒ Object
-
#limited_protected_branches(limit) ⇒ Object
-
#link_pool_repository ⇒ Object
-
#log_import_activity(job_id, type: :import) ⇒ Object
-
#mark_pages_as_deployed(artifacts_archive: nil) ⇒ Object
rubocop: enable CodeReuse/ServiceClass.
-
#mark_pages_as_not_deployed ⇒ Object
-
#mark_remote_mirrors_for_removal ⇒ Object
-
#mark_stuck_remote_mirrors_as_failed! ⇒ Object
-
#max_attachment_size ⇒ Object
-
#members_among(users) ⇒ Object
Filters `users` to return only authorized users of the project.
-
#merge_base_commit(first_commit_id, second_commit_id) ⇒ Object
-
#merge_method ⇒ Object
-
#merge_method=(method) ⇒ Object
-
#merge_requests_allowing_push_to_user(user) ⇒ Object
-
#metrics_setting ⇒ Object
-
#migrate_to_hashed_storage! ⇒ Object
-
#monitoring_service ⇒ Object
-
#monitoring_services ⇒ Object
-
#multiple_issue_boards_available? ⇒ Boolean
-
#new_issuable_address(author, address_type) ⇒ Object
-
#object_pool_params ⇒ Object
-
#open_issues_count(current_user = nil) ⇒ Object
rubocop: disable CodeReuse/ServiceClass.
-
#open_merge_requests_count ⇒ Object
rubocop: disable CodeReuse/ServiceClass.
-
#origin_merge_requests ⇒ Object
-
#owner ⇒ Object
rubocop: enable CodeReuse/ServiceClass.
-
#package_already_taken?(package_name) ⇒ Boolean
-
#packages_enabled=(value) ⇒ Object
Because we use default_value_for we need to be sure packages_enabled= method does exist even if we rollback migration.
-
#pages_available? ⇒ Boolean
-
#pages_deployed? ⇒ Boolean
-
#pages_group_root? ⇒ Boolean
-
#pages_group_url ⇒ Object
-
#pages_https_only ⇒ Object
-
#pages_https_only? ⇒ Boolean
-
#pages_lookup_path(trim_prefix: nil, domain: nil) ⇒ Object
-
#pages_path ⇒ Object
-
#pages_subdomain ⇒ Object
-
#pages_url ⇒ Object
-
#pages_variables ⇒ Object
-
#parent_changed? ⇒ Boolean
-
#personal? ⇒ Boolean
-
#predefined_ci_server_variables ⇒ Object
-
#predefined_project_variables ⇒ Object
-
#predefined_variables ⇒ Object
-
#preload_protected_branches ⇒ Object
-
#project_id ⇒ Object
-
#project_member(user) ⇒ Object
-
#project_setting ⇒ Object
-
#protected_for?(ref) ⇒ Boolean
-
#public_path_for_source_path(path, commit_sha) ⇒ Object
-
#pushes_since_gc ⇒ Object
-
#readme_url ⇒ Object
-
#reference_counter(type: Gitlab::GlRepository::PROJECT) ⇒ Object
-
#regeneration_in_progress? ⇒ Boolean
-
#remote_mirror_available? ⇒ Boolean
-
#remove_exports ⇒ Object
-
#remove_import_data ⇒ Object
This method is overridden in EE::Project model.
-
#remove_pages ⇒ Object
TODO: what to do here when not using Legacy Storage? Do we still need to rename and delay removal? rubocop: disable CodeReuse/ServiceClass.
-
#remove_private_deploy_keys ⇒ Object
-
#renamed? ⇒ Boolean
-
#repository ⇒ Object
-
#reset_cache_and_import_attrs ⇒ Object
-
#reset_pushes_since_gc ⇒ Object
-
#rollback_to_legacy_storage! ⇒ Object
-
#root_namespace ⇒ Object
-
#route_map_for(commit_sha) ⇒ Object
-
#runners_token ⇒ Object
-
#safe_import_url ⇒ Object
-
#saved? ⇒ Boolean
-
#self_monitoring? ⇒ Boolean
-
#send_move_instructions(old_path_with_namespace) ⇒ Object
rubocop: disable CodeReuse/ServiceClass.
-
#service_desk_address ⇒ Object
-
#service_desk_custom_address ⇒ Object
-
#service_desk_enabled ⇒ Object
(also: #service_desk_enabled?)
-
#service_desk_incoming_address ⇒ Object
-
#set_repository_read_only! ⇒ Boolean
Tries to set repository as read_only, checking for existing Git transfers in progress beforehand.
-
#set_repository_writable! ⇒ Object
Set repository as writable again.
-
#shared_runners ⇒ Object
-
#shared_runners_available? ⇒ Boolean
-
#should_validate_visibility_level? ⇒ Boolean
-
#snippets_visible?(user = nil) ⇒ Boolean
-
#storage ⇒ Object
-
#storage_upgradable? ⇒ Boolean
-
#storage_version=(value) ⇒ Object
-
#team ⇒ Object
-
#template_source? ⇒ Boolean
-
#to_ability_name ⇒ Object
-
#to_human_reference(from = nil) ⇒ Object
-
#to_param ⇒ Object
-
#to_reference(from = nil, full: false) ⇒ Object
Produce a valid reference (see Referable#to_reference).
-
#to_reference_base(from = nil, full: false) ⇒ Object
`from` argument can be a Namespace or Project.
-
#toggle_ci_cd_settings!(settings_attribute) ⇒ Object
-
#track_project_repository ⇒ Object
-
#uncached_ci_variables_for(ref:, environment: nil) ⇒ Object
-
#unlink_forks_upon_visibility_decrease_enabled? ⇒ Boolean
-
#update_forks_visibility_level ⇒ Object
update visibility_level of forks.
-
#update_project_counter_caches ⇒ Object
-
#update_remote_mirrors ⇒ Object
-
#updating_remote_mirror? ⇒ Boolean
-
#uses_default_ci_config? ⇒ Boolean
-
#valid_import_url? ⇒ Boolean
-
#valid_runners_token?(token) ⇒ Boolean
-
#validate_pages_https_only ⇒ Object
-
#visibility_level_allowed?(level = self.visibility_level) ⇒ Boolean
-
#visibility_level_allowed_as_fork ⇒ Object
-
#visibility_level_allowed_as_fork?(level = self.visibility_level) ⇒ Boolean
rubocop: enable CodeReuse/ServiceClass.
-
#visibility_level_allowed_by_group ⇒ Object
-
#visibility_level_allowed_by_group?(level = self.visibility_level) ⇒ Boolean
-
#visibility_level_field ⇒ Object
-
#write_repository_config(gl_full_path: full_path) ⇒ Object
gitlab_config, gitlab_config_features
extended, request_cache, request_cache_key
#flipper_id
#dependent_associations_to_destroy, #destroy_dependent_associations_in_batches
#retrieve_upload
#perform_fast_destroy
#run_after_commit, #run_after_commit_or_now
#chronic_duration_attributes, #output_chronic_duration_attribute
#clear_memoization, #strong_memoize, #strong_memoized?
#deployment_platform
build_hierarchy, #hierarchy
Methods included from Routable
#build_full_path, #full_name, #full_path, #full_path_components, #owned_by?
Methods included from HasWiki
#create_wiki, #wiki, #wiki_repository_exists?
#commit, #commit_by, #commits_by, #default_branch, #default_branch_from_preferences, #empty_repo?, #full_path, #http_url_to_repo, #reload_default_branch, #repo_exists?, #repository_exists?, #repository_size_checker, #root_ref?, #ssh_url_to_repo, #url_to_repo, #valid_repo?, #web_url
#gitlab_shell
Methods included from Referable
#referable_inspect, #reference_link_text
#present
#builds_access_level=, #builds_enabled=, #forking_access_level=, #issues_access_level=, #issues_enabled=, #merge_requests_access_level=, #merge_requests_enabled=, #metrics_dashboard_access_level=, #pages_access_level=, #repository_access_level=, #snippets_access_level=, #snippets_enabled=, #wiki_access_level=, #wiki_enabled=
#auto_devops_deploy_strategy=, #auto_devops_enabled=, #build_git_strategy=
#valid_attribute?
#attribute_invalidated?, #banzai_render_context, #cached_html_for, #cached_html_up_to_date?, #can_cache_field?, #invalidated_markdown_cache?, #latest_cached_markdown_version, #local_version, #parent_user, #refresh_markdown_cache, #refresh_markdown_cache!, #rendered_field_content, #skip_project_check?, #updated_cached_html_for
Methods included from Avatarable
#avatar_path, #avatar_type, #uncached_avatar_path, #upload_paths
#request_access
allowed_for?, allowed_level?, allowed_levels, closest_allowed_level, #internal?, level_name, level_value, levels_for_user, non_restricted_level?, options, #private?, #public?, public_visibility_restricted?, restricted_level?, string_level, string_options, string_values, valid_level?, #visibility, #visibility=, #visibility_attribute_present?, #visibility_level_attributes, #visibility_level_decreased?, #visibility_level_previous_changes, #visibility_level_value
at_most, id_in, id_not_in, iid_in, pluck_primary_key, primary_key_in, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, underscore, without_order
Constructor Details
#initialize(attributes = nil) ⇒ Project
Returns a new instance of Project.
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
|
# File 'app/models/project.rb', line 773
def initialize(attributes = nil)
attributes ||= {}
unless visibility_attribute_present?(attributes)
attributes[:visibility_level] = Gitlab::CurrentSettings.default_project_visibility
end
super
end
|
Instance Attribute Details
#old_path_with_namespace ⇒ Object
Returns the value of attribute old_path_with_namespace
125
126
127
|
# File 'app/models/project.rb', line 125
def old_path_with_namespace
@old_path_with_namespace
end
|
#pipeline_status ⇒ Object
Lazy loading of the `pipeline_status` attribute
#skip_disk_validation ⇒ Object
Returns the value of attribute skip_disk_validation
128
129
130
|
# File 'app/models/project.rb', line 128
def skip_disk_validation
@skip_disk_validation
end
|
#template_name ⇒ Object
Returns the value of attribute template_name
126
127
128
|
# File 'app/models/project.rb', line 126
def template_name
@template_name
end
|
Class Method Details
.cached_count ⇒ Object
745
746
747
748
749
|
# File 'app/models/project.rb', line 745
def cached_count
Rails.cache.fetch('total_project_count', expires_in: 5.minutes) do
Project.count
end
end
|
.eager_load_namespace_and_owner ⇒ Object
584
585
586
|
# File 'app/models/project.rb', line 584
def self.eager_load_namespace_and_owner
includes(namespace: :owner)
end
|
.filter_by_feature_visibility(feature, user) ⇒ Object
This scope returns projects where user has access to both the project and the feature.
.find_by_service_desk_project_key(key) ⇒ Object
766
767
768
769
770
|
# File 'app/models/project.rb', line 766
def find_by_service_desk_project_key(key)
joins(:service_desk_setting).find_by('service_desk_settings.project_key' => key)
end
|
.group_ids ⇒ Object
751
752
753
|
# File 'app/models/project.rb', line 751
def group_ids
joins(:namespace).where(namespaces: { type: 'Group' }).select(:namespace_id)
end
|
.ids_with_issuables_available_for(user) ⇒ Object
Returns ids of projects with issuables available for given user
Used on queries to find milestones or labels which user can see For example: Milestone.where(project_id: ids_with_issuables_available_for(user))
759
760
761
762
763
764
|
# File 'app/models/project.rb', line 759
def ids_with_issuables_available_for(user)
with_issues_enabled = with_issues_available_for_user(user).select(:id)
with_merge_requests_enabled = with_merge_requests_available_for_user(user).select(:id)
from_union([with_issues_enabled, with_merge_requests_enabled]).select(:id)
end
|
.markdown_reference_pattern ⇒ Object
Pattern used to extract `namespace/project>` project references from text. '>' or its escaped form ('>') are checked for because '>' is sometimes escaped when the reference comes from an external source.
732
733
734
735
736
737
738
|
# File 'app/models/project.rb', line 732
def markdown_reference_pattern
@markdown_reference_pattern ||=
%r{
#{reference_pattern}
(#{reference_postfix}|#{reference_postfix_escaped})
}x
end
|
.projects_user_can(projects, user, action) ⇒ Object
637
638
639
640
641
642
643
|
# File 'app/models/project.rb', line 637
def self.projects_user_can(projects, user, action)
projects = where(id: projects)
DeclarativePolicy.user_scope do
projects.select { |project| Ability.allowed?(user, action, project) }
end
end
|
.public_or_visible_to_user(user = nil, min_access_level = nil) ⇒ Object
Returns a collection of projects that is either public or visible to the logged in user.
590
591
592
593
594
595
596
597
598
599
600
601
602
|
# File 'app/models/project.rb', line 590
def self.public_or_visible_to_user(user = nil, min_access_level = nil)
min_access_level = nil if user&.admin?
return public_to_user unless user
if user.is_a?(DeployToken)
user.projects
else
where('EXISTS (?) OR projects.visibility_level IN (?)',
user.authorizations_for_projects(min_access_level: min_access_level),
Gitlab::VisibilityLevel.levels_for_user(user))
end
end
|
.reference_pattern ⇒ Object
.reference_postfix ⇒ Object
721
722
723
|
# File 'app/models/project.rb', line 721
def reference_postfix
'>'
end
|
.reference_postfix_escaped ⇒ Object
725
726
727
|
# File 'app/models/project.rb', line 725
def reference_postfix_escaped
'>'
end
|
.search(query, include_namespace: false) ⇒ Object
Searches for a list of projects based on the query given in `query`.
On PostgreSQL this method uses “ILIKE” to perform a case-insensitive search.
query - The search query as a String.
678
679
680
681
682
683
684
|
# File 'app/models/project.rb', line 678
def search(query, include_namespace: false)
if include_namespace
joins(:route).fuzzy_search(query, [Route.arel_table[:path], Route.arel_table[:name], :description])
else
fuzzy_search(query, [:path, :name, :description])
end
end
|
.search_by_title(query) ⇒ Object
686
687
688
|
# File 'app/models/project.rb', line 686
def search_by_title(query)
non_archived.fuzzy_search(query, [:name])
end
|
.sort_by_attribute(method) ⇒ Object
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
|
# File 'app/models/project.rb', line 694
def sort_by_attribute(method)
case method.to_s
when 'storage_size_desc'
reorder('project_statistics.storage_size DESC, projects.id DESC')
when 'latest_activity_desc'
reorder(self.arel_table['last_activity_at'].desc)
when 'latest_activity_asc'
reorder(self.arel_table['last_activity_at'].asc)
when 'stars_desc'
sorted_by_stars_desc
when 'stars_asc'
sorted_by_stars_asc
else
order_by(method)
end
end
|
.trending ⇒ Object
740
741
742
743
|
# File 'app/models/project.rb', line 740
def trending
joins('INNER JOIN trending_projects ON projects.id = trending_projects.project_id')
.reorder('trending_projects.id ASC')
end
|
.visibility_levels ⇒ Object
.with_api_entity_associations ⇒ Object
576
577
578
|
# File 'app/models/project.rb', line 576
def self.with_api_entity_associations
preload(:project_feature, :route, :tags, :group, namespace: [:route, :owner])
end
|
.with_feature_available_for_user(feature, user) ⇒ Object
project features may be “disabled”, “internal”, “enabled” or “public”. If “internal”, they are only available to team members. This scope returns projects where the feature is either public, enabled, or internal with permission for the user. Note: this scope doesn't enforce that the user has access to the projects, it just checks that the user has access to the feature. It's important to use this scope with others that checks project authorizations first (e.g. `filter_by_feature_visibility`).
This method uses an optimised version of `with_feature_access_level` for logged in users to more efficiently get private projects with the given feature.
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
|
# File 'app/models/project.rb', line 614
def self.with_feature_available_for_user(feature, user)
visible = [ProjectFeature::ENABLED, ProjectFeature::PUBLIC]
if user&.admin?
with_feature_enabled(feature)
elsif user
min_access_level = ProjectFeature.required_minimum_access_level(feature)
column = ProjectFeature.quoted_access_level_column(feature)
with_project_feature
.where("#{column} IS NULL OR #{column} IN (:public_visible) OR (#{column} = :private_visible AND EXISTS (:authorizations))",
{
public_visible: visible,
private_visible: ProjectFeature::PRIVATE,
authorizations: user.authorizations_for_projects(min_access_level: min_access_level)
})
else
visible << nil
with_feature_access_level(feature, visible)
end
end
|
.with_web_entity_associations ⇒ Object
580
581
582
|
# File 'app/models/project.rb', line 580
def self.with_web_entity_associations
preload(:project_feature, :route, :creator, :group, namespace: [:route, :owner])
end
|
.wrap_with_cte(collection) ⇒ Object
654
655
656
657
|
# File 'app/models/project.rb', line 654
def self.wrap_with_cte(collection)
cte = Gitlab::SQL::CTE.new(:projects_cte, collection)
Project.with(cte.to_arel).from(cte.alias_to(Project.arel_table))
end
|
Instance Method Details
#access_request_approvers_to_be_notified ⇒ Object
#active_runners ⇒ Object
1710
1711
1712
1713
1714
|
# File 'app/models/project.rb', line 1710
def active_runners
strong_memoize(:active_runners) do
all_runners.active
end
end
|
#active_webide_pipelines(user:) ⇒ Object
812
813
814
|
# File 'app/models/project.rb', line 812
def active_webide_pipelines(user:)
webide_pipelines.running_or_pending.for_user(user)
end
|
#add_export_job(current_user:, after_export_strategy: nil, params: {}) ⇒ Object
1891
1892
1893
1894
1895
1896
1897
1898
1899
|
# File 'app/models/project.rb', line 1891
def add_export_job(current_user:, after_export_strategy: nil, params: {})
job_id = ProjectExportWorker.perform_async(current_user.id, self.id, after_export_strategy, params)
if job_id
Gitlab::AppLogger.info "Export job started for project ID #{self.id} with job ID #{job_id}"
else
Gitlab::AppLogger.error "Export job failed to start for project ID #{self.id}"
end
end
|
#add_import_job ⇒ Object
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
|
# File 'app/models/project.rb', line 988
def add_import_job
job_id =
if forked?
RepositoryForkWorker.perform_async(id)
elsif gitlab_project_import?
RepositoryImportWorker.set(retry: false).perform_async(self.id)
else
RepositoryImportWorker.perform_async(self.id)
end
log_import_activity(job_id)
job_id
end
|
#after_create_default_branch ⇒ Object
rubocop: disable CodeReuse/ServiceClass
#after_import ⇒ Object
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
|
# File 'app/models/project.rb', line 1849
def after_import
repository.expire_content_cache
wiki.repository.expire_content_cache
DetectRepositoryLanguagesWorker.perform_async(id)
InternalId.flush_records!(project: self)
import_state.finish
update_project_counter_caches
after_create_default_branch
join_pool_repository
refresh_markdown_cache!
write_repository_config
end
|
#alerts_service_activated? ⇒ Boolean
2441
2442
2443
|
# File 'app/models/project.rb', line 2441
def alerts_service_activated?
alerts_service&.active?
end
|
#all_clusters ⇒ Object
1381
1382
1383
1384
1385
1386
|
# File 'app/models/project.rb', line 1381
def all_clusters
group_clusters = Clusters::Cluster.joins(:groups).where(cluster_groups: { group_id: ancestors_upto } )
instance_clusters = Clusters::Cluster.instance_type
Clusters::Cluster.from_union([clusters, group_clusters, instance_clusters])
end
|
#all_lfs_objects ⇒ Object
This will return all `lfs_objects` that are accessible to the project and the fork source. This is needed since older forks won't have access to some LFS objects directly and have to get it from the fork source.
TODO: Remove this method once all LfsObjectsProject records are backfilled for forks. At that point, projects can look at their own `lfs_objects`.
See gitlab.com/gitlab-org/gitlab/issues/122002 for more info.
1496
1497
1498
1499
1500
1501
|
# File 'app/models/project.rb', line 1496
def all_lfs_objects
LfsObject
.distinct
.joins(:lfs_objects_projects)
.where(lfs_objects_projects: { project_id: [self, lfs_storage_project] })
end
|
#all_lfs_objects_oids(oids: []) ⇒ Object
TODO: Remove this method once all LfsObjectsProject records are backfilled for forks. At that point, projects can look at their own `lfs_objects` so `lfs_objects_oids` can be used instead.
See gitlab.com/gitlab-org/gitlab/issues/122002 for more info.
1508
1509
1510
|
# File 'app/models/project.rb', line 1508
def all_lfs_objects_oids(oids: [])
oids(all_lfs_objects, oids: oids)
end
|
#all_pipelines ⇒ Object
796
797
798
799
800
801
802
|
# File 'app/models/project.rb', line 796
def all_pipelines
if builds_enabled?
super
else
super.external
end
end
|
#all_runners ⇒ Object
1706
1707
1708
|
# File 'app/models/project.rb', line 1706
def all_runners
Ci::Runner.from_union([runners, group_runners, shared_runners])
end
|
#allowed_to_share_with_group? ⇒ Boolean
1669
1670
1671
|
# File 'app/models/project.rb', line 1669
def allowed_to_share_with_group?
!namespace.share_with_group_lock
end
|
#ancestors_upto(top = nil, hierarchy_order: nil) ⇒ Object
Also known as:
ancestors
returns all ancestor-groups upto but excluding the given namespace when no namespace is given, all ancestors upto the top are returned
829
830
831
832
|
# File 'app/models/project.rb', line 829
def ancestors_upto(top = nil, hierarchy_order: nil)
Gitlab::ObjectHierarchy.new(Group.where(id: namespace_id))
.base_and_ancestors(upto: top, hierarchy_order: hierarchy_order)
end
|
#any_branch_allows_collaboration?(user) ⇒ Boolean
2310
2311
2312
|
# File 'app/models/project.rb', line 2310
def any_branch_allows_collaboration?(user)
fetch_branch_allows_collaboration(user)
end
|
#any_lfs_file_locks? ⇒ Boolean
2335
2336
2337
|
# File 'app/models/project.rb', line 2335
def any_lfs_file_locks?
lfs_file_locks.any?
end
|
#any_runners?(&block) ⇒ Boolean
1716
1717
1718
|
# File 'app/models/project.rb', line 1716
def any_runners?(&block)
active_runners.any?(&block)
end
|
#auto_cancel_pending_pipelines? ⇒ Boolean
2340
2341
2342
|
# File 'app/models/project.rb', line 2340
def auto_cancel_pending_pipelines?
auto_cancel_pending_pipelines == 'enabled'
end
|
#auto_devops_enabled? ⇒ Boolean
851
852
853
854
855
856
857
|
# File 'app/models/project.rb', line 851
def auto_devops_enabled?
if auto_devops&.enabled.nil?
has_auto_devops_implicitly_enabled?
else
auto_devops.enabled?
end
end
|
#auto_devops_variables ⇒ Object
2103
2104
2105
2106
2107
|
# File 'app/models/project.rb', line 2103
def auto_devops_variables
return [] unless auto_devops_enabled?
(auto_devops || build_auto_devops)&.predefined_variables
end
|
#autoclose_referenced_issues ⇒ Object
816
817
818
819
820
|
# File 'app/models/project.rb', line 816
def autoclose_referenced_issues
return true if super.nil?
super
end
|
#avatar_in_git ⇒ Object
1368
1369
1370
|
# File 'app/models/project.rb', line 1368
def avatar_in_git
repository.avatar
end
|
#avatar_url(**args) ⇒ Object
1372
1373
1374
|
# File 'app/models/project.rb', line 1372
def avatar_url(**args)
Gitlab::Routing.url_helpers.project_avatar_url(self) if avatar_in_git
end
|
#badges ⇒ Object
2290
2291
2292
2293
2294
2295
2296
2297
|
# File 'app/models/project.rb', line 2290
def badges
return project_badges unless group
Badge.from_union([
project_badges,
GroupBadge.where(group: group.self_and_ancestors)
])
end
|
#bare_repository_import? ⇒ Boolean
1083
1084
1085
|
# File 'app/models/project.rb', line 1083
def bare_repository_import?
import_type == 'bare_repository'
end
|
#bots ⇒ Object
1604
1605
1606
|
# File 'app/models/project.rb', line 1604
def bots
users.project_bot
end
|
#branch_allows_collaboration?(user, branch_name) ⇒ Boolean
2314
2315
2316
|
# File 'app/models/project.rb', line 2314
def branch_allows_collaboration?(user, branch_name)
fetch_branch_allows_collaboration(user, branch_name)
end
|
#build_commit_note(commit) ⇒ Object
1245
1246
1247
|
# File 'app/models/project.rb', line 1245
def build_commit_note(commit)
notes.new(commit_id: commit.id, noteable_type: 'Commit')
end
|
#cache_has_external_issue_tracker ⇒ Object
1297
1298
1299
|
# File 'app/models/project.rb', line 1297
def cache_has_external_issue_tracker
update_column(:has_external_issue_tracker, services.external_issue_trackers.any?) if Gitlab::Database.read_write?
end
|
#cache_has_external_wiki ⇒ Object
1321
1322
1323
|
# File 'app/models/project.rb', line 1321
def cache_has_external_wiki
update_column(:has_external_wiki, services.external_wikis.any?) if Gitlab::Database.read_write?
end
|
#change_head(branch) ⇒ Object
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
|
# File 'app/models/project.rb', line 1624
def change_head(branch)
if repository.branch_exists?(branch)
repository.before_change_head
repository.raw_repository.write_ref('HEAD', "refs/heads/#{branch}")
repository.copy_gitattributes(branch)
repository.after_change_head
ProjectCacheWorker.perform_async(self.id, [], [:commit_count])
reload_default_branch
else
errors.add(:base, _("Could not change HEAD: branch '%{branch}' does not exist") % { branch: branch })
false
end
end
|
#check_personal_projects_limit ⇒ Object
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
|
# File 'app/models/project.rb', line 1130
def check_personal_projects_limit
return if !creator || creator.can_create_project? ||
namespace.kind == 'group'
limit = creator.projects_limit
error =
if limit == 0
_('Personal project creation is not allowed. Please contact your administrator with questions')
else
_('Your project limit is %{limit} projects! Please contact your administrator to increase it')
end
self.errors.add(:limit_reached, error % { limit: limit })
end
|
#check_repository_path_availability ⇒ Object
Check if repository already exists on disk
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
|
# File 'app/models/project.rb', line 1532
def check_repository_path_availability
return true if skip_disk_validation
return false unless repository_storage
if legacy_storage? && repository_with_same_path_already_exists?
errors.add(:base, _('There is already a repository with that name on disk'))
return false
end
true
rescue GRPC::Internal false
end
|
#ci_config_path=(value) ⇒ Object
1028
1029
1030
1031
|
# File 'app/models/project.rb', line 1028
def ci_config_path=(value)
super(value&.delete("\0"))
end
|
#ci_config_path_or_default ⇒ Object
2526
2527
2528
|
# File 'app/models/project.rb', line 2526
def ci_config_path_or_default
ci_config_path.presence || Ci::Pipeline::DEFAULT_CONFIG_PATH
end
|
#ci_instance_variables_for(ref:) ⇒ Object
#ci_pipelines ⇒ Object
804
805
806
807
808
809
810
|
# File 'app/models/project.rb', line 804
def ci_pipelines
if builds_enabled?
super
else
super.external
end
end
|
#ci_service ⇒ Object
1356
1357
1358
|
# File 'app/models/project.rb', line 1356
def ci_service
@ci_service ||= ci_services.reorder(nil).find_by(active: true)
end
|
#ci_services ⇒ Object
rubocop: enable CodeReuse/ServiceClass
1352
1353
1354
|
# File 'app/models/project.rb', line 1352
def ci_services
services.where(category: :ci)
end
|
#ci_variables_for(ref:, environment: nil) ⇒ Object
2042
2043
2044
2045
2046
2047
2048
|
# File 'app/models/project.rb', line 2042
def ci_variables_for(ref:, environment: nil)
cache_key = "ci_variables_for:project:#{self&.id}:ref:#{ref}:environment:#{environment}"
::Gitlab::SafeRequestStore.fetch(cache_key) do
uncached_ci_variables_for(ref: ref, environment: environment)
end
end
|
#cleanup ⇒ Object
Also known as:
reload_repository!
917
918
919
|
# File 'app/models/project.rb', line 917
def cleanup
@repository = nil
end
|
#closest_setting(name) ⇒ Object
2408
2409
2410
2411
2412
2413
|
# File 'app/models/project.rb', line 2408
def closest_setting(name)
setting = read_attribute(name)
setting = closest_namespace_setting(name) if setting.nil?
setting = app_settings_for(name) if setting.nil?
setting
end
|
#code ⇒ Object
For compatibility with old code
1377
1378
1379
|
# File 'app/models/project.rb', line 1377
def code
path
end
|
#container_registry_url ⇒ Object
923
924
925
926
927
|
# File 'app/models/project.rb', line 923
def container_registry_url
if Gitlab.config.registry.enabled
"#{Gitlab.config.registry.host_port}/#{full_path.downcase}"
end
end
|
#container_registry_variables ⇒ Object
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
|
# File 'app/models/project.rb', line 2021
def container_registry_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
break variables unless Gitlab.config.registry.enabled
variables.append(key: 'CI_REGISTRY', value: Gitlab.config.registry.host_port)
if container_registry_enabled?
variables.append(key: 'CI_REGISTRY_IMAGE', value: container_registry_url)
end
end
end
|
#context_commits_enabled? ⇒ Boolean
885
886
887
|
# File 'app/models/project.rb', line 885
def context_commits_enabled?
Feature.enabled?(:context_commits, default_enabled: true)
end
|
#create_labels ⇒ Object
rubocop: disable CodeReuse/ServiceClass
1344
1345
1346
1347
1348
1349
|
# File 'app/models/project.rb', line 1344
def create_labels
Label.templates.each do |label|
params = label.attributes.except('id', 'template', 'created_at', 'updated_at', 'type')
Labels::FindOrCreateService.new(nil, self, params).execute(skip_authorization: true)
end
end
|
#create_or_update_import_data(data: nil, credentials: nil) ⇒ Object
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
|
# File 'app/models/project.rb', line 1060
def create_or_update_import_data(data: nil, credentials: nil)
return if data.nil? && credentials.nil?
project_import_data = import_data || build_import_data
project_import_data.merge_data(data.to_h)
project_import_data.merge_credentials(credentials.to_h)
project_import_data
end
|
#create_repository(force: false) ⇒ Object
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
|
# File 'app/models/project.rb', line 1553
def create_repository(force: false)
return if forked? && !force
repository.create_repository
repository.after_create
true
rescue => err
Gitlab::ErrorTracking.track_exception(err, project: { id: id, full_path: full_path, disk_path: disk_path })
errors.add(:base, _('Failed to create repository'))
false
end
|
#default_branch_or_master ⇒ Object
2522
2523
2524
|
# File 'app/models/project.rb', line 2522
def default_branch_or_master
default_branch || 'master'
end
|
#default_branch_protected? ⇒ Boolean
2457
2458
2459
2460
2461
|
# File 'app/models/project.rb', line 2457
def default_branch_protected?
branch_protection = Gitlab::Access::BranchProtection.new(self.namespace.default_branch_protection)
branch_protection.fully_protected? || branch_protection.developer_can_merge?
end
|
#default_environment ⇒ Object
2033
2034
2035
2036
2037
2038
2039
2040
|
# File 'app/models/project.rb', line 2033
def default_environment
production_first = Arel.sql("(CASE WHEN name = 'production' THEN 0 ELSE 1 END), id ASC")
environments
.with_state(:available)
.reorder(production_first)
.first
end
|
#default_issues_tracker? ⇒ Boolean
1279
1280
1281
|
# File 'app/models/project.rb', line 1279
def default_issues_tracker?
!external_issue_tracker
end
|
#default_merge_request_target ⇒ Object
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
|
# File 'app/models/project.rb', line 2164
def default_merge_request_target
return self unless forked_from_project
return self unless forked_from_project.merge_requests_enabled?
if visibility_level_value < forked_from_project.visibility_level_value
self
else
forked_from_project
end
end
|
#default_owner ⇒ Object
1411
1412
1413
1414
1415
1416
1417
1418
1419
|
# File 'app/models/project.rb', line 1411
def default_owner
obj = owner
if obj.respond_to?(:default_owner)
obj.default_owner
else
obj
end
end
|
#deploy_token_create_url(opts = {}) ⇒ Object
2449
2450
2451
|
# File 'app/models/project.rb', line 2449
def deploy_token_create_url(opts = {})
Gitlab::Routing.url_helpers.create_deploy_token_project_settings_repository_path(self, opts)
end
|
#deploy_token_revoke_url_for(token) ⇒ Object
2453
2454
2455
|
# File 'app/models/project.rb', line 2453
def deploy_token_revoke_url_for(token)
Gitlab::Routing.url_helpers.revoke_project_deploy_token_path(self, token)
end
|
#deployment_variables(environment:, kubernetes_namespace: nil) ⇒ Object
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
|
# File 'app/models/project.rb', line 2091
def deployment_variables(environment:, kubernetes_namespace: nil)
platform = deployment_platform(environment: environment)
return [] unless platform.present?
platform.predefined_variables(
project: self,
environment_name: environment,
kubernetes_namespace: kubernetes_namespace
)
end
|
#design_management_enabled? ⇒ Boolean
LFS and hashed repository storage are required for using Design Management.
890
891
892
|
# File 'app/models/project.rb', line 890
def design_management_enabled?
lfs_enabled? && hashed_storage?(:repository)
end
|
#design_repository ⇒ Object
902
903
904
905
906
|
# File 'app/models/project.rb', line 902
def design_repository
strong_memoize(:design_repository) do
Gitlab::GlRepository::DESIGN.repository_for(self)
end
end
|
#disabled_services ⇒ Object
1333
1334
1335
|
# File 'app/models/project.rb', line 1333
def disabled_services
[]
end
|
#drop_visibility_level! ⇒ Object
2415
2416
2417
2418
2419
2420
2421
2422
2423
|
# File 'app/models/project.rb', line 2415
def drop_visibility_level!
if group && group.visibility_level < visibility_level
self.visibility_level = group.visibility_level
end
if Gitlab::CurrentSettings.restricted_visibility_levels.include?(visibility_level)
self.visibility_level = Gitlab::VisibilityLevel::PRIVATE
end
end
|
#emails_disabled? ⇒ Boolean
836
837
838
839
840
841
|
# File 'app/models/project.rb', line 836
def emails_disabled?
strong_memoize(:emails_disabled) do
super || namespace.emails_disabled?
end
end
|
#enable_ci ⇒ Object
1690
1691
1692
|
# File 'app/models/project.rb', line 1690
def enable_ci
project_feature.update_attribute(:builds_access_level, ProjectFeature::ENABLED)
end
|
#enabled_group_deploy_keys ⇒ Object
2530
2531
2532
2533
2534
|
# File 'app/models/project.rb', line 2530
def enabled_group_deploy_keys
return GroupDeployKey.none unless group
GroupDeployKey.for_groups(group.self_and_ancestors_ids)
end
|
#ensure_repository ⇒ Object
1652
1653
1654
|
# File 'app/models/project.rb', line 1652
def ensure_repository
create_repository(force: true) unless repository_exists?
end
|
#environments_for_scope(scope) ⇒ Object
2463
2464
2465
2466
2467
|
# File 'app/models/project.rb', line 2463
def environments_for_scope(scope)
quoted_scope = ::Gitlab::SQL::Glob.q(scope)
environments.where("name LIKE (#{::Gitlab::SQL::Glob.to_like(quoted_scope)})") end
|
#execute_hooks(data, hooks_scope = :push_hooks) ⇒ Object
rubocop: disable CodeReuse/ServiceClass
1426
1427
1428
1429
1430
1431
1432
1433
|
# File 'app/models/project.rb', line 1426
def execute_hooks(data, hooks_scope = :push_hooks)
run_after_commit_or_now do
hooks.hooks_for(hooks_scope).select_active(hooks_scope, data).each do |hook|
hook.async_execute(data, hooks_scope.to_s)
end
SystemHooksService.new.execute_hooks(data, hooks_scope)
end
end
|
#execute_services(data, hooks_scope = :push_hooks) ⇒ Object
rubocop: enable CodeReuse/ServiceClass
1436
1437
1438
1439
1440
1441
1442
1443
|
# File 'app/models/project.rb', line 1436
def execute_services(data, hooks_scope = :push_hooks)
run_after_commit_or_now do
services.public_send(hooks_scope).each do |service| service.async_execute(data)
end
end
end
|
#expire_caches_before_rename(old_path) ⇒ Object
Expires various caches before a project is renamed.
1521
1522
1523
1524
1525
1526
1527
1528
1529
|
# File 'app/models/project.rb', line 1521
def expire_caches_before_rename(old_path)
project_repo = Repository.new(old_path, self, shard: repository_storage)
wiki_repo = Repository.new("#{old_path}#{Gitlab::GlRepository::WIKI.path_suffix}", self, shard: repository_storage, repo_type: Gitlab::GlRepository::WIKI)
design_repo = Repository.new("#{old_path}#{Gitlab::GlRepository::DESIGN.path_suffix}", self, shard: repository_storage, repo_type: Gitlab::GlRepository::DESIGN)
[project_repo, wiki_repo, design_repo].each do |repo|
repo.before_delete if repo.exists?
end
end
|
#export_enqueued? ⇒ Boolean
1931
1932
1933
1934
1935
|
# File 'app/models/project.rb', line 1931
def export_enqueued?
strong_memoize(:export_enqueued) do
::Projects::ExportJobFinder.new(self, { status: :queued }).execute.present?
end
end
|
#export_file ⇒ Object
1952
1953
1954
|
# File 'app/models/project.rb', line 1952
def export_file
import_export_upload&.export_file
end
|
#export_file_exists? ⇒ Boolean
1948
1949
1950
|
# File 'app/models/project.rb', line 1948
def export_file_exists?
export_file&.file
end
|
#export_in_progress? ⇒ Boolean
1925
1926
1927
1928
1929
|
# File 'app/models/project.rb', line 1925
def export_in_progress?
strong_memoize(:export_in_progress) do
::Projects::ExportJobFinder.new(self, { status: :started }).execute.present?
end
end
|
#export_path ⇒ Object
1905
1906
1907
1908
1909
|
# File 'app/models/project.rb', line 1905
def export_path
return unless namespace.present? || hashed_storage?(:repository)
import_export_shared.archive_path
end
|
#export_status ⇒ Object
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
|
# File 'app/models/project.rb', line 1911
def export_status
if regeneration_in_progress?
:regeneration_in_progress
elsif export_enqueued?
:queued
elsif export_in_progress?
:started
elsif export_file_exists?
:finished
else
:none
end
end
|
#external_authorization_classification_label ⇒ Object
#external_import? ⇒ Boolean
1075
1076
1077
|
# File 'app/models/project.rb', line 1075
def external_import?
import_url.present?
end
|
#external_issue_reference_pattern ⇒ Object
1275
1276
1277
|
# File 'app/models/project.rb', line 1275
def external_issue_reference_pattern
external_issue_tracker.class.reference_pattern(only_long: issues_enabled?)
end
|
#external_issue_tracker ⇒ Object
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
|
# File 'app/models/project.rb', line 1283
def external_issue_tracker
if has_external_issue_tracker.nil?
cache_has_external_issue_tracker
end
if has_external_issue_tracker?
strong_memoize(:external_issue_tracker) do
services.external_issue_trackers.first
end
else
nil
end
end
|
#external_references_supported? ⇒ Boolean
1301
1302
1303
|
# File 'app/models/project.rb', line 1301
def external_references_supported?
external_issue_tracker&.support_cross_reference?
end
|
#external_wiki ⇒ Object
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
|
# File 'app/models/project.rb', line 1309
def external_wiki
if has_external_wiki.nil?
cache_has_external_wiki
end
if has_external_wiki
@external_wiki ||= services.external_wikis.first
else
nil
end
end
|
#feature_usage ⇒ Object
1458
1459
1460
|
# File 'app/models/project.rb', line 1458
def feature_usage
super.presence || build_feature_usage
end
|
#ff_merge_must_be_possible? ⇒ Boolean
2252
2253
2254
|
# File 'app/models/project.rb', line 2252
def ff_merge_must_be_possible?
self.merge_requests_ff_only_enabled || self.merge_requests_rebase_enabled
end
|
#find_or_initialize_service(name) ⇒ Object
1337
1338
1339
1340
1341
|
# File 'app/models/project.rb', line 1337
def find_or_initialize_service(name)
return if disabled_services.include?(name)
find_service(services, name) || build_from_instance_or_template(name) || public_send("build_#{name}_service") end
|
#find_or_initialize_services ⇒ Object
1325
1326
1327
1328
1329
1330
1331
|
# File 'app/models/project.rb', line 1325
def find_or_initialize_services
available_services_names = Service.available_services_names - disabled_services
available_services_names.map do |service_name|
find_or_initialize_service(service_name)
end.sort_by(&:title)
end
|
#first_auto_devops_config ⇒ Object
875
876
877
878
879
|
# File 'app/models/project.rb', line 875
def first_auto_devops_config
return namespace.first_auto_devops_config if auto_devops&.enabled.nil?
{ scope: :project, status: auto_devops&.enabled || Feature.enabled?(:force_autodevops_on_by_default, self) }
end
|
#fork_source ⇒ Object
1466
1467
1468
1469
1470
|
# File 'app/models/project.rb', line 1466
def fork_source
return unless forked?
forked_from_project || fork_network&.root_project
end
|
#forked? ⇒ Boolean
1462
1463
1464
|
# File 'app/models/project.rb', line 1462
def forked?
fork_network && fork_network.root_project != self
end
|
#forked_from?(other_project) ⇒ Boolean
1638
1639
1640
|
# File 'app/models/project.rb', line 1638
def forked_from?(other_project)
forked? && forked_from_project == other_project
end
|
#forks_count ⇒ Object
rubocop: disable CodeReuse/ServiceClass
2192
2193
2194
2195
2196
2197
2198
2199
2200
|
# File 'app/models/project.rb', line 2192
def forks_count
BatchLoader.for(self).batch do |projects, loader|
fork_count_per_project = ::Projects::BatchForksCountService.new(projects).refresh_cache_and_retrieve_data
fork_count_per_project.each do |project, count|
loader.call(project, count)
end
end
end
|
#full_path_before_last_save ⇒ Object
2182
2183
2184
|
# File 'app/models/project.rb', line 2182
def full_path_before_last_save
File.join(namespace.full_path, path_before_last_save)
end
|
#full_path_slug ⇒ Object
1956
1957
1958
|
# File 'app/models/project.rb', line 1956
def full_path_slug
Gitlab::Utils.slugify(full_path.to_s)
end
|
#get_issue(issue_id, current_user) ⇒ Object
1261
1262
1263
1264
1265
1266
1267
1268
1269
|
# File 'app/models/project.rb', line 1261
def get_issue(issue_id, current_user)
issue = IssuesFinder.new(current_user, project_id: id).find_by(iid: issue_id) if issues_enabled?
if issue
issue
elsif external_issue_tracker
ExternalIssue.new(issue_id, self)
end
end
|
#git_objects_poolable? ⇒ Boolean
Git objects are only poolable when the project is or has:
-
Hashed storage -> The object pool will have a remote to its members, using relative paths.
If the repository path changes we would have to update the remote.
-
not private -> The visibility level or repository access level has to be greater than private
to prevent fetching objects that might not exist
-
Repository -> Else the disk path will be empty, and there's nothing to pool
#git_transfer_in_progress? ⇒ Boolean
2276
2277
2278
|
# File 'app/models/project.rb', line 2276
def git_transfer_in_progress?
repo_reference_count > 0 || wiki_reference_count > 0
end
|
#gitea_import? ⇒ Boolean
1095
1096
1097
|
# File 'app/models/project.rb', line 1095
def gitea_import?
import_type == 'gitea'
end
|
#gitlab_deploy_token ⇒ Object
2331
2332
2333
|
# File 'app/models/project.rb', line 2331
def gitlab_deploy_token
@gitlab_deploy_token ||= deploy_tokens.gitlab_deploy_token
end
|
#gitlab_project_import? ⇒ Boolean
1091
1092
1093
|
# File 'app/models/project.rb', line 1091
def gitlab_project_import?
import_type == 'gitlab_project'
end
|
#group_runners ⇒ Object
1702
1703
1704
|
# File 'app/models/project.rb', line 1702
def group_runners
@group_runners ||= group_runners_enabled? ? Ci::Runner.belonging_to_parent_group_of_project(self.id) : Ci::Runner.none
end
|
#has_active_hooks?(hooks_scope = :push_hooks) ⇒ Boolean
1445
1446
1447
|
# File 'app/models/project.rb', line 1445
def has_active_hooks?(hooks_scope = :push_hooks)
hooks.hooks_for(hooks_scope).any? || SystemHook.hooks_for(hooks_scope).any? || Gitlab::FileHook.any?
end
|
#has_active_services?(hooks_scope = :push_hooks) ⇒ Boolean
1449
1450
1451
|
# File 'app/models/project.rb', line 1449
def has_active_services?(hooks_scope = :push_hooks)
services.public_send(hooks_scope).any? end
|
#has_auto_devops_implicitly_disabled? ⇒ Boolean
865
866
867
868
869
|
# File 'app/models/project.rb', line 865
def has_auto_devops_implicitly_disabled?
auto_devops_config = first_auto_devops_config
auto_devops_config[:scope] != :project && !auto_devops_config[:status]
end
|
#has_auto_devops_implicitly_enabled? ⇒ Boolean
859
860
861
862
863
|
# File 'app/models/project.rb', line 859
def has_auto_devops_implicitly_enabled?
auto_devops_config = first_auto_devops_config
auto_devops_config[:scope] != :project && auto_devops_config[:status]
end
|
#has_ci? ⇒ Boolean
1960
1961
1962
|
# File 'app/models/project.rb', line 1960
def has_ci?
repository.gitlab_ci_yml || auto_devops_enabled?
end
|
929
930
931
932
933
934
|
# File 'app/models/project.rb', line 929
def has_container_registry_tags?
return @images if defined?(@images)
@images = container_repositories.to_a.any?(&:has_tags?) ||
has_root_container_repository_tags?
end
|
#has_packages?(package_type) ⇒ Boolean
871
872
873
|
# File 'app/models/project.rb', line 871
def has_packages?(package_type)
packages.where(package_type: package_type).exists?
end
|
#has_pool_repository? ⇒ Boolean
2396
2397
2398
|
# File 'app/models/project.rb', line 2396
def has_pool_repository?
pool_repository.present?
end
|
#has_remote_mirror? ⇒ Boolean
1099
1100
1101
|
# File 'app/models/project.rb', line 1099
def has_remote_mirror?
remote_mirror_available? && remote_mirrors.enabled.exists?
end
|
#has_wiki? ⇒ Boolean
1305
1306
1307
|
# File 'app/models/project.rb', line 1305
def has_wiki?
wiki_enabled? || has_external_wiki?
end
|
#hashed_storage?(feature) ⇒ Boolean
Check if Hashed Storage is enabled for the project with at least informed feature rolled out
2210
2211
2212
2213
2214
|
# File 'app/models/project.rb', line 2210
def hashed_storage?(feature)
raise ArgumentError, _("Invalid feature") unless HASHED_STORAGE_FEATURES.include?(feature)
self.storage_version && self.storage_version >= HASHED_STORAGE_FEATURES[feature]
end
|
#hook_attrs(backward: true) ⇒ Object
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
|
# File 'app/models/project.rb', line 1567
def hook_attrs(backward: true)
attrs = {
id: id,
name: name,
description: description,
web_url: web_url,
avatar_url: avatar_url(only_path: false),
git_ssh_url: ssh_url_to_repo,
git_http_url: http_url_to_repo,
namespace: namespace.name,
visibility_level: visibility_level,
path_with_namespace: full_path,
default_branch: default_branch,
ci_config_path: ci_config_path
}
if backward
attrs.merge!({
homepage: web_url,
url: url_to_repo,
ssh_url: ssh_url_to_repo,
http_url: http_url_to_repo
})
end
attrs
end
|
#human_import_status_name ⇒ Object
984
985
986
|
# File 'app/models/project.rb', line 984
def human_import_status_name
import_state&.human_status_name || 'none'
end
|
#human_merge_method ⇒ Object
2220
2221
2222
2223
2224
2225
2226
|
# File 'app/models/project.rb', line 2220
def human_merge_method
if merge_method == :ff
'Fast-forward'
else
merge_method.to_s.humanize
end
end
|
#import? ⇒ Boolean
1071
1072
1073
|
# File 'app/models/project.rb', line 1071
def import?
external_import? || forked? || gitlab_project_import? || jira_import? || bare_repository_import?
end
|
#import_export_shared ⇒ Object
1901
1902
1903
|
# File 'app/models/project.rb', line 1901
def import_export_shared
@import_export_shared ||= Gitlab::ImportExport::Shared.new(self)
end
|
#import_status ⇒ Object
976
977
978
|
# File 'app/models/project.rb', line 976
def import_status
import_state&.status || 'none'
end
|
#import_url ⇒ Object
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
|
# File 'app/models/project.rb', line 1045
def import_url
if import_data && super.present?
import_url = Gitlab::UrlSanitizer.new(super, credentials: import_data.credentials)
import_url.full_url
else
super
end
rescue
super
end
|
#import_url=(value) ⇒ Object
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
|
# File 'app/models/project.rb', line 1033
def import_url=(value)
if Gitlab::UrlSanitizer.valid?(value)
import_url = Gitlab::UrlSanitizer.new(value)
super(import_url.sanitized_url)
credentials = import_url.credentials.to_h.transform_values { |value| CGI.unescape(value.to_s) }
create_or_update_import_data(credentials: credentials)
else
super(value)
end
end
|
#in_fork_network_of?(other_project) ⇒ Boolean
1642
1643
1644
1645
1646
|
# File 'app/models/project.rb', line 1642
def in_fork_network_of?(other_project)
return false if fork_network.nil? || other_project.fork_network.nil?
fork_network == other_project.fork_network
end
|
#increment_pushes_since_gc ⇒ Object
2131
2132
2133
|
# File 'app/models/project.rb', line 2131
def increment_pushes_since_gc
Gitlab::Redis::SharedState.with { |redis| redis.incr(pushes_since_gc_redis_shared_state_key) }
end
|
#issue_exists?(issue_id) ⇒ Boolean
1271
1272
1273
|
# File 'app/models/project.rb', line 1271
def issue_exists?(issue_id)
get_issue(issue_id)
end
|
#items_for(entity) ⇒ Object
1388
1389
1390
1391
1392
1393
1394
1395
|
# File 'app/models/project.rb', line 1388
def items_for(entity)
case entity
when 'issue' then
issues
when 'merge_request' then
merge_requests
end
end
|
#jira_import? ⇒ Boolean
1087
1088
1089
|
# File 'app/models/project.rb', line 1087
def jira_import?
import_type == 'jira' && latest_jira_import.present?
end
|
#jira_import_status ⇒ Object
980
981
982
|
# File 'app/models/project.rb', line 980
def jira_import_status
latest_jira_import&.status || 'initial'
end
|
#jira_subscription_exists? ⇒ Boolean
2429
2430
2431
|
# File 'app/models/project.rb', line 2429
def jira_subscription_exists?
JiraConnectSubscription.for_project(self).exists?
end
|
#last_activity ⇒ Object
1249
1250
1251
|
# File 'app/models/project.rb', line 1249
def last_activity
last_event
end
|
#last_activity_date ⇒ Object
1253
1254
1255
|
# File 'app/models/project.rb', line 1253
def last_activity_date
[last_activity_at, last_repository_updated_at, updated_at].compact.max
end
|
#latest_jira_import ⇒ Object
2469
2470
2471
|
# File 'app/models/project.rb', line 2469
def latest_jira_import
jira_imports.last
end
|
#latest_pipeline(ref = default_branch, sha = nil) ⇒ Object
959
960
961
962
963
964
965
|
# File 'app/models/project.rb', line 959
def latest_pipeline(ref = default_branch, sha = nil)
ref = ref.presence || default_branch
sha ||= commit(ref)&.sha
return unless sha
ci_pipelines.newest_first(ref: ref, sha: sha).take
end
|
#latest_successful_build_for_ref(job_name, ref = default_branch) ⇒ Object
ref can't be HEAD, can only be branch/tag name
937
938
939
940
941
942
943
944
|
# File 'app/models/project.rb', line 937
def latest_successful_build_for_ref(job_name, ref = default_branch)
return unless ref
latest_pipeline = ci_pipelines.latest_successful_for_ref(ref)
return unless latest_pipeline
latest_pipeline.builds.latest.with_downloadable_artifacts.find_by(name: job_name)
end
|
#latest_successful_build_for_ref!(job_name, ref = default_branch) ⇒ Object
955
956
957
|
# File 'app/models/project.rb', line 955
def latest_successful_build_for_ref!(job_name, ref = default_branch)
latest_successful_build_for_ref(job_name, ref) || raise(ActiveRecord::RecordNotFound.new("Couldn't find job #{job_name}"))
end
|
#latest_successful_build_for_sha(job_name, sha) ⇒ Object
946
947
948
949
950
951
952
953
|
# File 'app/models/project.rb', line 946
def latest_successful_build_for_sha(job_name, sha)
return unless sha
latest_pipeline = ci_pipelines.latest_successful_for_sha(sha)
return unless latest_pipeline
latest_pipeline.builds.latest.with_downloadable_artifacts.find_by(name: job_name)
end
|
#latest_successful_pipeline_for(ref = nil) ⇒ Object
1682
1683
1684
1685
1686
1687
1688
|
# File 'app/models/project.rb', line 1682
def latest_successful_pipeline_for(ref = nil)
if ref && ref != default_branch
ci_pipelines.latest_successful_for_ref(ref)
else
latest_successful_pipeline_for_default_branch
end
end
|
#latest_successful_pipeline_for_default_branch ⇒ Object
1673
1674
1675
1676
1677
1678
1679
1680
|
# File 'app/models/project.rb', line 1673
def latest_successful_pipeline_for_default_branch
if defined?(@latest_successful_pipeline_for_default_branch)
return @latest_successful_pipeline_for_default_branch
end
@latest_successful_pipeline_for_default_branch =
ci_pipelines.latest_successful_for_ref(default_branch)
end
|
#leave_pool_repository ⇒ Object
2388
2389
2390
|
# File 'app/models/project.rb', line 2388
def leave_pool_repository
pool_repository&.mark_obsolete_if_last(repository) && update_column(:pool_repository_id, nil)
end
|
#legacy_storage? ⇒ Boolean
rubocop: enable CodeReuse/ServiceClass
2203
2204
2205
|
# File 'app/models/project.rb', line 2203
def legacy_storage?
[nil, 0].include?(self.storage_version)
end
|
#lfs_enabled? ⇒ Boolean
Also known as:
lfs_enabled
843
844
845
846
847
|
# File 'app/models/project.rb', line 843
def lfs_enabled?
return namespace.lfs_enabled? if self[:lfs_enabled].nil?
self[:lfs_enabled] && Gitlab.config.lfs.enabled
end
|
#lfs_http_url_to_repo(_) ⇒ Object
1454
1455
1456
|
# File 'app/models/project.rb', line 1454
def lfs_http_url_to_repo(_)
http_url_to_repo
end
|
#lfs_objects_oids(oids: []) ⇒ Object
1512
1513
1514
|
# File 'app/models/project.rb', line 1512
def lfs_objects_oids(oids: [])
oids(lfs_objects, oids: oids)
end
|
#lfs_storage_project ⇒ Object
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
|
# File 'app/models/project.rb', line 1476
def lfs_storage_project
@lfs_storage_project ||= begin
result = self
result = result.fork_source while result&.forked?
result || self
end
end
|
#licensed_features ⇒ Object
2323
2324
2325
|
# File 'app/models/project.rb', line 2323
def licensed_features
[]
end
|
#limited_protected_branches(limit) ⇒ Object
2437
2438
2439
|
# File 'app/models/project.rb', line 2437
def limited_protected_branches(limit)
protected_branches.limit(limit)
end
|
#link_pool_repository ⇒ Object
2392
2393
2394
|
# File 'app/models/project.rb', line 2392
def link_pool_repository
pool_repository&.link_repository(repository)
end
|
#log_import_activity(job_id, type: :import) ⇒ Object
1004
1005
1006
1007
1008
1009
1010
1011
1012
|
# File 'app/models/project.rb', line 1004
def log_import_activity(job_id, type: :import)
job_type = type.to_s.capitalize
if job_id
Gitlab::AppLogger.info("#{job_type} job scheduled for #{full_path} with job ID #{job_id}.")
else
Gitlab::AppLogger.error("#{job_type} job failed to create for #{full_path}.")
end
end
|
#mark_pages_as_deployed(artifacts_archive: nil) ⇒ Object
rubocop: enable CodeReuse/ServiceClass
1831
1832
1833
|
# File 'app/models/project.rb', line 1831
def mark_pages_as_deployed(artifacts_archive: nil)
ensure_pages_metadatum.update!(deployed: true, artifacts_archive: artifacts_archive)
end
|
#mark_pages_as_not_deployed ⇒ Object
1835
1836
1837
|
# File 'app/models/project.rb', line 1835
def mark_pages_as_not_deployed
ensure_pages_metadatum.update!(deployed: false, artifacts_archive: nil)
end
|
#mark_remote_mirrors_for_removal ⇒ Object
1121
1122
1123
|
# File 'app/models/project.rb', line 1121
def mark_remote_mirrors_for_removal
remote_mirrors.each(&:mark_for_delete_if_blank_url)
end
|
#mark_stuck_remote_mirrors_as_failed! ⇒ Object
1113
1114
1115
1116
1117
1118
1119
|
# File 'app/models/project.rb', line 1113
def mark_stuck_remote_mirrors_as_failed!
remote_mirrors.stuck.update_all(
update_status: :failed,
last_error: _('The remote mirror took to long to complete.'),
last_update_at: Time.current
)
end
|
#max_attachment_size ⇒ Object
2361
2362
2363
|
# File 'app/models/project.rb', line 2361
def max_attachment_size
Gitlab::CurrentSettings.max_attachment_size.megabytes.to_i
end
|
#members_among(users) ⇒ Object
Filters `users` to return only authorized users of the project
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
|
# File 'app/models/project.rb', line 1609
def members_among(users)
if users.is_a?(ActiveRecord::Relation) && !users.loaded?
authorized_users.merge(users)
else
return [] if users.empty?
user_ids = authorized_users.where(users: { id: users.map(&:id) }).pluck(:id)
users.select { |user| user_ids.include?(user.id) }
end
end
|
#merge_base_commit(first_commit_id, second_commit_id) ⇒ Object
967
968
969
970
|
# File 'app/models/project.rb', line 967
def merge_base_commit(first_commit_id, second_commit_id)
sha = repository.merge_base(first_commit_id, second_commit_id)
commit_by(oid: sha) if sha
end
|
#merge_method ⇒ Object
2228
2229
2230
2231
2232
2233
2234
2235
2236
|
# File 'app/models/project.rb', line 2228
def merge_method
if self.merge_requests_ff_only_enabled
:ff
elsif self.merge_requests_rebase_enabled
:rebase_merge
else
:merge
end
end
|
#merge_method=(method) ⇒ Object
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
|
# File 'app/models/project.rb', line 2238
def merge_method=(method)
case method.to_s
when "ff"
self.merge_requests_ff_only_enabled = true
self.merge_requests_rebase_enabled = true
when "rebase_merge"
self.merge_requests_ff_only_enabled = false
self.merge_requests_rebase_enabled = true
when "merge"
self.merge_requests_ff_only_enabled = false
self.merge_requests_rebase_enabled = false
end
end
|
#merge_requests_allowing_push_to_user(user) ⇒ Object
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
|
# File 'app/models/project.rb', line 2299
def merge_requests_allowing_push_to_user(user)
return MergeRequest.none unless user
developer_access_exists = user.project_authorizations
.where('access_level >= ? ', Gitlab::Access::DEVELOPER)
.where('project_authorizations.project_id = merge_requests.target_project_id')
.limit(1)
.select(1)
merge_requests_allowing_collaboration.where('EXISTS (?)', developer_access_exists)
end
|
#metrics_setting ⇒ Object
2473
2474
2475
|
# File 'app/models/project.rb', line 2473
def metrics_setting
super || build_metrics_setting
end
|
#migrate_to_hashed_storage! ⇒ Object
#monitoring_service ⇒ Object
1364
1365
1366
|
# File 'app/models/project.rb', line 1364
def monitoring_service
@monitoring_service ||= monitoring_services.reorder(nil).find_by(active: true)
end
|
#monitoring_services ⇒ Object
1360
1361
1362
|
# File 'app/models/project.rb', line 1360
def monitoring_services
services.where(category: :monitoring)
end
|
#multiple_issue_boards_available? ⇒ Boolean
2178
2179
2180
|
# File 'app/models/project.rb', line 2178
def multiple_issue_boards_available?
true
end
|
#new_issuable_address(author, address_type) ⇒ Object
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
|
# File 'app/models/project.rb', line 1230
def new_issuable_address(author, address_type)
return unless Gitlab::IncomingEmail.supports_issue_creation? && author
return unless %w(issue merge_request).include?(address_type)
author.ensure_incoming_email_token!
suffix = address_type.dasherize
Gitlab::IncomingEmail.reply_address("#{full_path_slug}-#{project_id}-#{author.incoming_email_token}-#{suffix}")
end
|
#object_pool_params ⇒ Object
2365
2366
2367
2368
2369
2370
2371
2372
|
# File 'app/models/project.rb', line 2365
def object_pool_params
return {} unless !forked? && git_objects_poolable?
{
repository_storage: repository_storage,
pool_repository: pool_repository || create_new_pool_repository
}
end
|
#open_issues_count(current_user = nil) ⇒ Object
rubocop: disable CodeReuse/ServiceClass
#open_merge_requests_count ⇒ Object
rubocop: disable CodeReuse/ServiceClass
#origin_merge_requests ⇒ Object
1648
1649
1650
|
# File 'app/models/project.rb', line 1648
def origin_merge_requests
merge_requests.where(source_project_id: self.id)
end
|
#owner ⇒ Object
rubocop: enable CodeReuse/ServiceClass
1407
1408
1409
|
# File 'app/models/project.rb', line 1407
def owner
group || namespace.try(:owner)
end
|
#package_already_taken?(package_name) ⇒ Boolean
2514
2515
2516
2517
2518
2519
2520
|
# File 'app/models/project.rb', line 2514
def package_already_taken?(package_name)
namespace.root_ancestor.all_projects
.joins(:packages)
.where.not(id: id)
.merge(Packages::Package.with_name(package_name))
.exists?
end
|
#packages_enabled=(value) ⇒ Object
Because we use default_value_for we need to be sure packages_enabled= method does exist even if we rollback migration. Otherwise many tests from spec/migrations will fail.
911
912
913
914
915
|
# File 'app/models/project.rb', line 911
def packages_enabled=(value)
if has_attribute?(:packages_enabled)
write_attribute(:packages_enabled, value)
end
end
|
#pages_available? ⇒ Boolean
1793
1794
1795
|
# File 'app/models/project.rb', line 1793
def pages_available?
Gitlab.config.pages.enabled
end
|
#pages_deployed? ⇒ Boolean
1759
1760
1761
|
# File 'app/models/project.rb', line 1759
def pages_deployed?
pages_metadatum&.deployed?
end
|
#pages_group_root? ⇒ Boolean
1780
1781
1782
|
# File 'app/models/project.rb', line 1780
def pages_group_root?
pages_group_url == pages_url
end
|
#pages_group_url ⇒ Object
1763
1764
1765
1766
1767
1768
|
# File 'app/models/project.rb', line 1763
def pages_group_url
Gitlab.config.pages.url.sub(%r{^https?://}) do |prefix|
"#{prefix}#{pages_subdomain}."
end.downcase
end
|
#pages_https_only ⇒ Object
1167
1168
1169
1170
1171
|
# File 'app/models/project.rb', line 1167
def pages_https_only
return false unless Gitlab.config.pages.external_https
super
end
|
#pages_https_only? ⇒ Boolean
1173
1174
1175
1176
1177
|
# File 'app/models/project.rb', line 1173
def pages_https_only?
return false unless Gitlab.config.pages.external_https
super
end
|
#pages_lookup_path(trim_prefix: nil, domain: nil) ⇒ Object
2404
2405
2406
|
# File 'app/models/project.rb', line 2404
def pages_lookup_path(trim_prefix: nil, domain: nil)
Pages::LookupPath.new(self, trim_prefix: trim_prefix, domain: domain)
end
|
#pages_path ⇒ Object
1788
1789
1790
1791
|
# File 'app/models/project.rb', line 1788
def pages_path
File.join(Settings.pages.path, full_path)
end
|
#pages_subdomain ⇒ Object
1784
1785
1786
|
# File 'app/models/project.rb', line 1784
def pages_subdomain
full_path.partition('/').first
end
|
#pages_url ⇒ Object
1770
1771
1772
1773
1774
1775
1776
1777
1778
|
# File 'app/models/project.rb', line 1770
def pages_url
url = pages_group_url
url_path = full_path.partition('/').last
return url if url == "#{Settings.pages.protocol}://#{url_path}".downcase
"#{url}/#{url_path}"
end
|
#pages_variables ⇒ Object
2006
2007
2008
2009
2010
2011
2012
2013
|
# File 'app/models/project.rb', line 2006
def pages_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
break unless pages_enabled?
variables.append(key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host)
variables.append(key: 'CI_PAGES_URL', value: pages_url)
end
end
|
#parent_changed? ⇒ Boolean
2160
2161
2162
|
# File 'app/models/project.rb', line 2160
def parent_changed?
namespace_id_changed?
end
|
#personal? ⇒ Boolean
1516
1517
1518
|
# File 'app/models/project.rb', line 1516
def personal?
!group
end
|
#predefined_ci_server_variables ⇒ Object
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
|
# File 'app/models/project.rb', line 1990
def predefined_ci_server_variables
Gitlab::Ci::Variables::Collection.new
.append(key: 'CI', value: 'true')
.append(key: 'GITLAB_CI', value: 'true')
.append(key: 'CI_SERVER_URL', value: Gitlab.config.gitlab.url)
.append(key: 'CI_SERVER_HOST', value: Gitlab.config.gitlab.host)
.append(key: 'CI_SERVER_PORT', value: Gitlab.config.gitlab.port.to_s)
.append(key: 'CI_SERVER_PROTOCOL', value: Gitlab.config.gitlab.protocol)
.append(key: 'CI_SERVER_NAME', value: 'GitLab')
.append(key: 'CI_SERVER_VERSION', value: Gitlab::VERSION)
.append(key: 'CI_SERVER_VERSION_MAJOR', value: Gitlab.version_info.major.to_s)
.append(key: 'CI_SERVER_VERSION_MINOR', value: Gitlab.version_info.minor.to_s)
.append(key: 'CI_SERVER_VERSION_PATCH', value: Gitlab.version_info.patch.to_s)
.append(key: 'CI_SERVER_REVISION', value: Gitlab.revision)
end
|
#predefined_project_variables ⇒ Object
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
|
# File 'app/models/project.rb', line 1974
def predefined_project_variables
Gitlab::Ci::Variables::Collection.new
.append(key: 'GITLAB_FEATURES', value: licensed_features.join(','))
.append(key: 'CI_PROJECT_ID', value: id.to_s)
.append(key: 'CI_PROJECT_NAME', value: path)
.append(key: 'CI_PROJECT_TITLE', value: title)
.append(key: 'CI_PROJECT_PATH', value: full_path)
.append(key: 'CI_PROJECT_PATH_SLUG', value: full_path_slug)
.append(key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path)
.append(key: 'CI_PROJECT_ROOT_NAMESPACE', value: namespace.root_ancestor.path)
.append(key: 'CI_PROJECT_URL', value: web_url)
.append(key: 'CI_PROJECT_VISIBILITY', value: Gitlab::VisibilityLevel.string_level(visibility_level))
.append(key: 'CI_PROJECT_REPOSITORY_LANGUAGES', value: repository_languages.map(&:name).join(',').downcase)
.append(key: 'CI_DEFAULT_BRANCH', value: default_branch)
end
|
#predefined_variables ⇒ Object
1964
1965
1966
1967
1968
1969
1970
1971
1972
|
# File 'app/models/project.rb', line 1964
def predefined_variables
Gitlab::Ci::Variables::Collection.new
.concat(predefined_ci_server_variables)
.concat(predefined_project_variables)
.concat(pages_variables)
.concat(container_registry_variables)
.concat(auto_devops_variables)
.concat(api_variables)
end
|
#preload_protected_branches ⇒ Object
822
823
824
825
|
# File 'app/models/project.rb', line 822
def preload_protected_branches
preloader = ActiveRecord::Associations::Preloader.new
preloader.preload(self, protected_branches: [:push_access_levels, :merge_access_levels])
end
|
#project_id ⇒ Object
1257
1258
1259
|
# File 'app/models/project.rb', line 1257
def project_id
self.id
end
|
#project_member(user) ⇒ Object
1596
1597
1598
1599
1600
1601
1602
|
# File 'app/models/project.rb', line 1596
def project_member(user)
if project_members.loaded?
project_members.find { |member| member.user_id == user.id }
else
project_members.find_by(user_id: user)
end
end
|
#project_setting ⇒ Object
792
793
794
|
# File 'app/models/project.rb', line 792
def project_setting
super.presence || build_project_setting
end
|
#protected_for?(ref) ⇒ Boolean
#public_path_for_source_path(path, commit_sha) ⇒ Object
2153
2154
2155
2156
2157
2158
|
# File 'app/models/project.rb', line 2153
def public_path_for_source_path(path, commit_sha)
map = route_map_for(commit_sha)
return unless map
map.public_path_for_source_path(path)
end
|
#pushes_since_gc ⇒ Object
2127
2128
2129
|
# File 'app/models/project.rb', line 2127
def pushes_since_gc
Gitlab::Redis::SharedState.with { |redis| redis.get(pushes_since_gc_redis_shared_state_key).to_i }
end
|
#readme_url ⇒ Object
1223
1224
1225
1226
1227
1228
|
# File 'app/models/project.rb', line 1223
def readme_url
readme_path = repository.readme_path
if readme_path
Gitlab::Routing.url_helpers.project_blob_url(self, File.join(default_branch, readme_path))
end
end
|
#reference_counter(type: Gitlab::GlRepository::PROJECT) ⇒ Object
#regeneration_in_progress? ⇒ Boolean
1937
1938
1939
|
# File 'app/models/project.rb', line 1937
def regeneration_in_progress?
(export_enqueued? || export_in_progress?) && export_file_exists?
end
|
#remote_mirror_available? ⇒ Boolean
1125
1126
1127
1128
|
# File 'app/models/project.rb', line 1125
def remote_mirror_available?
remote_mirror_available_overridden ||
::Gitlab::CurrentSettings.mirror_available
end
|
#remove_exports ⇒ Object
1941
1942
1943
1944
1945
1946
|
# File 'app/models/project.rb', line 1941
def remove_exports
return unless export_file_exists?
import_export_upload.remove_export_file!
import_export_upload.save unless import_export_upload.destroyed?
end
|
#remove_import_data ⇒ Object
This method is overridden in EE::Project model
1024
1025
1026
|
# File 'app/models/project.rb', line 1024
def remove_import_data
import_data&.destroy
end
|
#remove_pages ⇒ Object
TODO: what to do here when not using Legacy Storage? Do we still need to rename and delay removal? rubocop: disable CodeReuse/ServiceClass
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
|
# File 'app/models/project.rb', line 1814
def remove_pages
return unless namespace
mark_pages_as_not_deployed unless destroyed?
temp_path = "#{path}.#{SecureRandom.hex}.deleted"
if Gitlab::PagesTransfer.new.rename_project(path, temp_path, namespace.full_path)
PagesWorker.perform_in(5.minutes, :remove, namespace.full_path, temp_path)
end
end
|
#remove_private_deploy_keys ⇒ Object
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
|
# File 'app/models/project.rb', line 1797
def remove_private_deploy_keys
exclude_keys_linked_to_other_projects = <<-SQL
NOT EXISTS (
SELECT 1
FROM deploy_keys_projects dkp2
WHERE dkp2.deploy_key_id = deploy_keys_projects.deploy_key_id
AND dkp2.project_id != deploy_keys_projects.project_id
)
SQL
deploy_keys.where(public: false)
.where(exclude_keys_linked_to_other_projects)
.delete_all
end
|
#renamed? ⇒ Boolean
2216
2217
2218
|
# File 'app/models/project.rb', line 2216
def renamed?
persisted? && path_changed?
end
|
#repository ⇒ Object
898
899
900
|
# File 'app/models/project.rb', line 898
def repository
@repository ||= Gitlab::GlRepository::PROJECT.repository_for(self)
end
|
#reset_cache_and_import_attrs ⇒ Object
1014
1015
1016
1017
1018
1019
1020
1021
|
# File 'app/models/project.rb', line 1014
def reset_cache_and_import_attrs
run_after_commit do
ProjectCacheWorker.perform_async(self.id)
end
import_state.update(last_error: nil)
remove_import_data
end
|
#reset_pushes_since_gc ⇒ Object
2135
2136
2137
|
# File 'app/models/project.rb', line 2135
def reset_pushes_since_gc
Gitlab::Redis::SharedState.with { |redis| redis.del(pushes_since_gc_redis_shared_state_key) }
end
|
#rollback_to_legacy_storage! ⇒ Object
#root_namespace ⇒ Object
2506
2507
2508
2509
2510
2511
2512
|
# File 'app/models/project.rb', line 2506
def root_namespace
if namespace.has_parent?
namespace.root_ancestor
else
namespace
end
end
|
#route_map_for(commit_sha) ⇒ Object
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
|
# File 'app/models/project.rb', line 2139
def route_map_for(commit_sha)
@route_maps_by_commit ||= Hash.new do |h, sha|
h[sha] = begin
data = repository.route_map_for(sha)
Gitlab::RouteMap.new(data) if data
rescue Gitlab::RouteMap::FormatError
nil
end
end
@route_maps_by_commit[commit_sha]
end
|
#runners_token ⇒ Object
1755
1756
1757
|
# File 'app/models/project.rb', line 1755
def runners_token
ensure_runners_token!
end
|
#safe_import_url ⇒ Object
#saved? ⇒ Boolean
972
973
974
|
# File 'app/models/project.rb', line 972
def saved?
id && persisted?
end
|
#self_monitoring? ⇒ Boolean
2445
2446
2447
|
# File 'app/models/project.rb', line 2445
def self_monitoring?
Gitlab::CurrentSettings.self_monitoring_project_id == id
end
|
#send_move_instructions(old_path_with_namespace) ⇒ Object
rubocop: disable CodeReuse/ServiceClass
1398
1399
1400
1401
1402
1403
1404
|
# File 'app/models/project.rb', line 1398
def send_move_instructions(old_path_with_namespace)
run_after_commit do
NotificationService.new.project_was_moved(self, old_path_with_namespace)
end
end
|
#service_desk_address ⇒ Object
2483
2484
2485
|
# File 'app/models/project.rb', line 2483
def service_desk_address
service_desk_custom_address || service_desk_incoming_address
end
|
#service_desk_custom_address ⇒ Object
#service_desk_enabled ⇒ Object
Also known as:
service_desk_enabled?
2477
2478
2479
|
# File 'app/models/project.rb', line 2477
def service_desk_enabled
Gitlab::ServiceDesk.enabled?(project: self)
end
|
#service_desk_incoming_address ⇒ Object
2487
2488
2489
2490
2491
2492
2493
2494
|
# File 'app/models/project.rb', line 2487
def service_desk_incoming_address
return unless service_desk_enabled?
config = Gitlab.config.incoming_email
wildcard = Gitlab::IncomingEmail::WILDCARD_PLACEHOLDER
config.address&.gsub(wildcard, "#{full_path_slug}-#{id}-issue-")
end
|
#set_repository_read_only! ⇒ Boolean
Tries to set repository as read_only, checking for existing Git transfers in progress beforehand
2112
2113
2114
2115
2116
2117
2118
|
# File 'app/models/project.rb', line 2112
def set_repository_read_only!
with_lock do
break false if git_transfer_in_progress?
update_column(:repository_read_only, true)
end
end
|
#set_repository_writable! ⇒ Object
Set repository as writable again
2121
2122
2123
2124
2125
|
# File 'app/models/project.rb', line 2121
def set_repository_writable!
with_lock do
update_column(:repository_read_only, false)
end
end
|
#shared_runners ⇒ Object
1698
1699
1700
|
# File 'app/models/project.rb', line 1698
def shared_runners
@shared_runners ||= shared_runners_available? ? Ci::Runner.instance_type : Ci::Runner.none
end
|
#shared_runners_available? ⇒ Boolean
1694
1695
1696
|
# File 'app/models/project.rb', line 1694
def shared_runners_available?
shared_runners_enabled?
end
|
#should_validate_visibility_level? ⇒ Boolean
1148
1149
1150
|
# File 'app/models/project.rb', line 1148
def should_validate_visibility_level?
new_record? || changes.has_key?(:visibility_level)
end
|
#snippets_visible?(user = nil) ⇒ Boolean
2357
2358
2359
|
# File 'app/models/project.rb', line 2357
def snippets_visible?(user = nil)
Ability.allowed?(user, :read_snippet, self)
end
|
#storage ⇒ Object
2344
2345
2346
2347
2348
2349
2350
2351
|
# File 'app/models/project.rb', line 2344
def storage
@storage ||=
if hashed_storage?(:repository)
Storage::Hashed.new(self)
else
Storage::LegacyProject.new(self)
end
end
|
#storage_upgradable? ⇒ Boolean
2353
2354
2355
|
# File 'app/models/project.rb', line 2353
def storage_upgradable?
storage_version != LATEST_STORAGE_VERSION
end
|
#storage_version=(value) ⇒ Object
2280
2281
2282
2283
2284
|
# File 'app/models/project.rb', line 2280
def storage_version=(value)
super
@storage = nil if storage_version_changed?
end
|
#team ⇒ Object
894
895
896
|
# File 'app/models/project.rb', line 894
def team
@team ||= ProjectTeam.new(self)
end
|
#template_source? ⇒ Boolean
2425
2426
2427
|
# File 'app/models/project.rb', line 2425
def template_source?
false
end
|
#to_ability_name ⇒ Object
1421
1422
1423
|
# File 'app/models/project.rb', line 1421
def to_ability_name
model_name.singular
end
|
#to_human_reference(from = nil) ⇒ Object
1215
1216
1217
1218
1219
1220
1221
|
# File 'app/models/project.rb', line 1215
def to_human_reference(from = nil)
if cross_namespace_reference?(from)
name_with_namespace
elsif cross_project_reference?(from)
name
end
end
|
#to_param ⇒ Object
1187
1188
1189
1190
1191
1192
1193
|
# File 'app/models/project.rb', line 1187
def to_param
if persisted? && errors.include?(:path)
path_was
else
path
end
end
|
#to_reference(from = nil, full: false) ⇒ Object
Produce a valid reference (see Referable#to_reference)
NB: For projects, all references are 'full' - i.e. they all include the full_path, rather than just the project name. For this reason, we ignore the value of `full:` passed to this method, which is part of the Referable interface.
1201
1202
1203
1204
|
# File 'app/models/project.rb', line 1201
def to_reference(from = nil, full: false)
base = to_reference_base(from, full: true)
"#{base}#{self.class.reference_postfix}"
end
|
#to_reference_base(from = nil, full: false) ⇒ Object
`from` argument can be a Namespace or Project.
1207
1208
1209
1210
1211
1212
1213
|
# File 'app/models/project.rb', line 1207
def to_reference_base(from = nil, full: false)
if full || cross_namespace_reference?(from)
full_path
elsif cross_project_reference?(from)
path
end
end
|
#toggle_ci_cd_settings!(settings_attribute) ⇒ Object
2327
2328
2329
|
# File 'app/models/project.rb', line 2327
def toggle_ci_cd_settings!(settings_attribute)
ci_cd_settings.toggle!(settings_attribute)
end
|
#track_project_repository ⇒ Object
1548
1549
1550
1551
|
# File 'app/models/project.rb', line 1548
def track_project_repository
repository = project_repository || build_project_repository
repository.update!(shard_name: repository_storage, disk_path: disk_path)
end
|
#uncached_ci_variables_for(ref:, environment: nil) ⇒ Object
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
|
# File 'app/models/project.rb', line 2050
def uncached_ci_variables_for(ref:, environment: nil)
result = if protected_for?(ref)
variables
else
variables.unprotected
end
if environment
result.on_environment(environment)
else
result.where(environment_scope: '*')
end
end
|
#unlink_forks_upon_visibility_decrease_enabled? ⇒ Boolean
881
882
883
|
# File 'app/models/project.rb', line 881
def unlink_forks_upon_visibility_decrease_enabled?
Feature.enabled?(:unlink_fork_network_upon_visibility_decrease, self, default_enabled: true)
end
|
#update_forks_visibility_level ⇒ Object
update visibility_level of forks
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
|
# File 'app/models/project.rb', line 1657
def update_forks_visibility_level
return if unlink_forks_upon_visibility_decrease_enabled?
return unless visibility_level < visibility_level_before_last_save
forks.each do |forked_project|
if forked_project.visibility_level > visibility_level
forked_project.visibility_level = visibility_level
forked_project.save!
end
end
end
|
#update_project_counter_caches ⇒ Object
#update_remote_mirrors ⇒ Object
1107
1108
1109
1110
1111
|
# File 'app/models/project.rb', line 1107
def update_remote_mirrors
return unless remote_mirror_available?
remote_mirrors.enabled.each(&:sync)
end
|
#updating_remote_mirror? ⇒ Boolean
1103
1104
1105
|
# File 'app/models/project.rb', line 1103
def updating_remote_mirror?
remote_mirrors.enabled.started.exists?
end
|
#uses_default_ci_config? ⇒ Boolean
2433
2434
2435
|
# File 'app/models/project.rb', line 2433
def uses_default_ci_config?
ci_config_path.blank? || ci_config_path == Gitlab::FileDetector::PATTERNS[:gitlab_ci]
end
|
#valid_import_url? ⇒ Boolean
1056
1057
1058
|
# File 'app/models/project.rb', line 1056
def valid_import_url?
valid?(:import_url) || errors.messages[:import_url].nil?
end
|
#valid_runners_token?(token) ⇒ Boolean
1720
1721
1722
|
# File 'app/models/project.rb', line 1720
def valid_runners_token?(token)
self.runners_token && ActiveSupport::SecurityUtils.secure_compare(token, self.runners_token)
end
|
#validate_pages_https_only ⇒ Object
1179
1180
1181
1182
1183
1184
1185
|
# File 'app/models/project.rb', line 1179
def validate_pages_https_only
return unless pages_https_only?
unless pages_domains.all?(&:https?)
errors.add(:pages_https_only, _("cannot be enabled unless all domains have TLS certificates"))
end
end
|
#visibility_level_allowed?(level = self.visibility_level) ⇒ Boolean
1751
1752
1753
|
# File 'app/models/project.rb', line 1751
def visibility_level_allowed?(level = self.visibility_level)
visibility_level_allowed_as_fork?(level) && visibility_level_allowed_by_group?(level)
end
|
#visibility_level_allowed_as_fork ⇒ Object
1160
1161
1162
1163
1164
1165
|
# File 'app/models/project.rb', line 1160
def visibility_level_allowed_as_fork
return if visibility_level_allowed_as_fork?
level_name = Gitlab::VisibilityLevel.level_name(self.visibility_level).downcase
self.errors.add(:visibility_level, _("%{level_name} is not allowed since the fork source project has lower visibility.") % { level_name: level_name })
end
|
#visibility_level_allowed_as_fork?(level = self.visibility_level) ⇒ Boolean
rubocop: enable CodeReuse/ServiceClass
1736
1737
1738
1739
1740
1741
1742
1743
|
# File 'app/models/project.rb', line 1736
def visibility_level_allowed_as_fork?(level = self.visibility_level)
return true unless forked?
original_project = fork_source
return true unless original_project
level <= original_project.visibility_level
end
|
#visibility_level_allowed_by_group ⇒ Object
1152
1153
1154
1155
1156
1157
1158
|
# File 'app/models/project.rb', line 1152
def visibility_level_allowed_by_group
return if visibility_level_allowed_by_group?
level_name = Gitlab::VisibilityLevel.level_name(self.visibility_level).downcase
group_level_name = Gitlab::VisibilityLevel.level_name(self.group.visibility_level).downcase
self.errors.add(:visibility_level, _("%{level_name} is not allowed in a %{group_level_name} group.") % { level_name: level_name, group_level_name: group_level_name })
end
|
#visibility_level_allowed_by_group?(level = self.visibility_level) ⇒ Boolean
1745
1746
1747
1748
1749
|
# File 'app/models/project.rb', line 1745
def visibility_level_allowed_by_group?(level = self.visibility_level)
return true unless group
level <= group.visibility_level
end
|
#visibility_level_field ⇒ Object
1620
1621
1622
|
# File 'app/models/project.rb', line 1620
def visibility_level_field
:visibility_level
end
|
#write_repository_config(gl_full_path: full_path) ⇒ Object
1839
1840
1841
1842
1843
1844
1845
1846
1847
|
# File 'app/models/project.rb', line 1839
def write_repository_config(gl_full_path: full_path)
repository.raw_repository.write_config(full_path: gl_full_path)
rescue Gitlab::Git::Repository::NoRepository => e
Gitlab::AppLogger.error("Error writing to .git/config for project #{full_path} (#{id}): #{e.message}.")
nil
end
|