......@@ -78,8 +78,8 @@ class Dashboard::TodosController < Dashboard::ApplicationController
def todos_counts
{
count: current_user.todos_pending_count,
done_count: current_user.todos_done_count
count: number_with_delimiter(current_user.todos_pending_count),
done_count: number_with_delimiter(current_user.todos_done_count)
}
end
......
......
......@@ -2,7 +2,6 @@
class Import::GithubController < Import::BaseController
include ImportHelper
include ActionView::Helpers::SanitizeHelper
before_action :verify_import_enabled
before_action :provider_auth, only: [:status, :realtime_changes, :create]
......@@ -56,7 +55,7 @@ class Import::GithubController < Import::BaseController
def realtime_changes
Gitlab::PollingInterval.set_header(response, interval: 3_000)
render json: already_added_projects.to_json(only: [:id], methods: [:import_status])
render json: find_jobs(provider)
end
private
......@@ -83,7 +82,7 @@ class Import::GithubController < Import::BaseController
end
def already_added_projects
@already_added_projects ||= filtered(find_already_added_projects(provider))
@already_added_projects ||= find_already_added_projects(provider)
end
def already_added_project_names
......@@ -105,7 +104,7 @@ class Import::GithubController < Import::BaseController
end
def client_repos
@client_repos ||= filtered(client.repos)
@client_repos ||= client.repos
end
def verify_import_enabled
......@@ -186,20 +185,6 @@ class Import::GithubController < Import::BaseController
def extra_import_params
{}
end
def sanitized_filter_param
@filter ||= sanitize(params[:filter])
end
def filter_attribute
:name
end
def filtered(collection)
return collection unless sanitized_filter_param
collection.select { |item| item[filter_attribute].include?(sanitized_filter_param) }
end
end
Import::GithubController.prepend_if_ee('EE::Import::GithubController')
......@@ -8,37 +8,10 @@ class Projects::ArtifactsController < Projects::ApplicationController
layout 'project'
before_action :authorize_read_build!
before_action :authorize_update_build!, only: [:keep]
before_action :authorize_destroy_artifacts!, only: [:destroy]
before_action :extract_ref_name_and_path
before_action :validate_artifacts!, except: [:index, :download, :destroy]
before_action :validate_artifacts!, except: [:download]
before_action :entry, only: [:file]
MAX_PER_PAGE = 20
def index
# Loading artifacts is very expensive in projects with a lot of artifacts.
# This feature flag prevents a DOS attack vector.
# It should be removed only after resolving the underlying performance
# issues: https://gitlab.com/gitlab-org/gitlab/issues/32281
return head :no_content unless Feature.enabled?(:artifacts_management_page, @project)
finder = ArtifactsFinder.new(@project, artifacts_params)
all_artifacts = finder.execute
@artifacts = all_artifacts.page(params[:page]).per(MAX_PER_PAGE)
@total_size = all_artifacts.total_size
end
def destroy
notice = if artifact.destroy
_('Artifact was successfully deleted.')
else
_('Artifact could not be deleted.')
end
redirect_to project_artifacts_path(@project), status: :see_other, notice: notice
end
def download
return render_404 unless artifacts_file
......@@ -101,10 +74,6 @@ class Projects::ArtifactsController < Projects::ApplicationController
@ref_name, @path = extract_ref(params[:ref_name_and_path])
end
def artifacts_params
params.permit(:sort)
end
def validate_artifacts!
render_404 unless build&.artifacts?
end
......@@ -116,11 +85,6 @@ class Projects::ArtifactsController < Projects::ApplicationController
end
end
def artifact
@artifact ||=
project.job_artifacts.find(params[:id])
end
def build_from_id
project.builds.find_by_id(params[:job_id]) if params[:job_id]
end
......
......
......@@ -19,12 +19,14 @@ module Projects
end
def destroy
result = Projects::ContainerRepository::DeleteTagsService
.new(image.project, current_user, tags: [params[:id]])
.execute(image)
if tag.delete
respond_to do |format|
format.json { head :no_content }
end
else
respond_to do |format|
format.json { head(result[:status] == :success ? :ok : bad_request) }
format.json { head :bad_request }
end
end
end
......@@ -40,12 +42,21 @@ module Projects
return
end
result = Projects::ContainerRepository::DeleteTagsService
.new(image.project, current_user, tags: tag_names)
.execute(image)
@tags = tag_names.map { |tag_name| image.tag(tag_name) }
unless @tags.all? { |tag| tag.valid_name? }
head :bad_request
return
end
success_count = 0
@tags.each do |tag|
if tag.delete
success_count += 1
end
end
respond_to do |format|
format.json { head(result[:status] == :success ? :no_content : :bad_request) }
format.json { head(success_count == @tags.size ? :no_content : :bad_request) }
end
end
......@@ -59,6 +70,10 @@ module Projects
@image ||= project.container_repositories
.find(params[:repository_id])
end
def tag
@tag ||= image.tag(params[:id])
end
end
end
end
......@@ -13,14 +13,6 @@ class Projects::TemplatesController < Projects::ApplicationController
end
end
def names
templates = @template_type.dropdown_names(project)
respond_to do |format|
format.json { render json: templates }
end
end
private
# User must have:
......
......
# frozen_string_literal: true
class ArtifactsFinder
def initialize(project, params = {})
@project = project
@params = params
end
def execute
artifacts = @project.job_artifacts
sort(artifacts)
end
private
def sort_key
@params[:sort] || 'created_desc'
end
def sort(artifacts)
artifacts.order_by(sort_key)
end
end
......@@ -272,7 +272,7 @@ module IssuablesHelper
markdownPreviewPath: preview_markdown_path(parent),
markdownDocsPath: help_page_path('user/markdown'),
lockVersion: issuable.lock_version,
issuableTemplateNamesPath: template_names_path(parent, issuable),
issuableTemplates: issuable_templates(issuable),
initialTitleHtml: markdown_field(issuable, :title),
initialTitleText: issuable.title,
initialDescriptionHtml: markdown_field(issuable, :description),
......@@ -429,12 +429,6 @@ module IssuablesHelper
end
end
def template_names_path(parent, issuable)
return '' unless parent.is_a?(Project)
project_template_names_path(parent, template_type: issuable.class.name.underscore)
end
def issuable_sidebar_options(issuable)
{
endpoint: "#{issuable[:issuable_json_path]}?serializer=sidebar_extras",
......
......
......@@ -34,15 +34,15 @@ module SearchHelper
from: from,
to: to,
count: count,
scope: search_entries_scope_label(scope, count),
scope: search_entries_info_label(scope, count),
term: term
}
end
def search_entries_scope_label(scope, count)
def search_entries_info_label(scope, count)
case scope
when 'blobs'
ns_('SearchResults|code result', 'SearchResults|code results', count)
when 'blobs', 'snippet_blobs', 'wiki_blobs'
ns_('SearchResults|result', 'SearchResults|results', count)
when 'commits'
ns_('SearchResults|commit', 'SearchResults|commits', count)
when 'issues'
......@@ -55,14 +55,10 @@ module SearchHelper
ns_('SearchResults|comment', 'SearchResults|comments', count)
when 'projects'
ns_('SearchResults|project', 'SearchResults|projects', count)
when 'snippet_blobs'
ns_('SearchResults|snippet result', 'SearchResults|snippet results', count)
when 'snippet_titles'
ns_('SearchResults|snippet', 'SearchResults|snippets', count)
when 'users'
ns_('SearchResults|user', 'SearchResults|users', count)
when 'wiki_blobs'
ns_('SearchResults|wiki result', 'SearchResults|wiki results', count)
else
raise "Unrecognized search scope '#{scope}'"
end
......@@ -76,13 +72,6 @@ module SearchHelper
end
end
def search_entries_empty_message(scope, term)
(s_("SearchResults|We couldn't find any %{scope} matching %{term}") % {
scope: search_entries_scope_label(scope, 0),
term: "<code>#{term}</code>"
}).html_safe
end
def find_project_for_result_blob(projects, result)
@project
end
......
......
......@@ -28,9 +28,7 @@ module SortingHelper
sort_value_priority => sort_title_priority,
sort_value_upvotes => sort_title_upvotes,
sort_value_contacted_date => sort_title_contacted_date,
sort_value_relative_position => sort_title_relative_position,
sort_value_size => sort_title_size,
sort_value_expire_date => sort_title_expire_date
sort_value_relative_position => sort_title_relative_position
}
end
......@@ -408,14 +406,6 @@ module SortingHelper
s_('SortOptions|Manual')
end
def sort_title_size
s_('SortOptions|Size')
end
def sort_title_expire_date
s_('SortOptions|Expired date')
end
# Values.
def sort_value_access_level_asc
'access_level_asc'
......@@ -568,12 +558,4 @@ module SortingHelper
def sort_value_relative_position
'relative_position'
end
def sort_value_size
'size_desc'
end
def sort_value_expire_date
'expired_asc'
end
end
......@@ -118,6 +118,8 @@ module Ci
scope :eager_load_job_artifacts, -> { includes(:job_artifacts) }
scope :with_artifacts_stored_locally, -> { with_existing_job_artifacts(Ci::JobArtifact.archive.with_files_stored_locally) }
scope :with_archived_trace_stored_locally, -> { with_existing_job_artifacts(Ci::JobArtifact.trace.with_files_stored_locally) }
scope :with_artifacts_not_expired, ->() { with_artifacts_archive.where('artifacts_expire_at IS NULL OR artifacts_expire_at > ?', Time.now) }
scope :with_expired_artifacts, ->() { with_artifacts_archive.where('artifacts_expire_at < ?', Time.now) }
scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) }
......
......
......@@ -5,7 +5,6 @@ module Ci
include AfterCommitQueue
include ObjectStorage::BackgroundMove
include UpdateProjectStatistics
include Sortable
extend Gitlab::Ci::Model
NotSupportedAdapterError = Class.new(StandardError)
......@@ -65,7 +64,6 @@ module Ci
after_save :update_file_store, if: :saved_change_to_file?
scope :with_files_stored_locally, -> { where(file_store: [nil, ::JobArtifactUploader::Store::LOCAL]) }
scope :with_files_stored_remotely, -> { where(file_store: ::JobArtifactUploader::Store::REMOTE) }
scope :with_file_types, -> (file_types) do
types = self.file_types.select { |file_type| file_types.include?(file_type) }.values
......@@ -145,10 +143,6 @@ module Ci
self.update_column(:file_store, file.object_store)
end
def self.total_size
self.sum(:size)
end
def self.artifacts_size_for(project)
self.where(project: project).sum(:size)
end
......
......
......@@ -39,7 +39,7 @@ module Clusters
def self.has_one_cluster_application(name) # rubocop:disable Naming/PredicateName
application = APPLICATIONS[name.to_s]
has_one application.association_name, class_name: application.to_s, inverse_of: :cluster # rubocop:disable Rails/ReflectionClassName
has_one application.association_name, class_name: application.to_s # rubocop:disable Rails/ReflectionClassName
end
has_one_cluster_application :helm
......
......
......@@ -9,7 +9,6 @@ class LfsObject < ApplicationRecord
has_many :projects, -> { distinct }, through: :lfs_objects_projects
scope :with_files_stored_locally, -> { where(file_store: LfsObjectUploader::Store::LOCAL) }
scope :with_files_stored_remotely, -> { where(file_store: LfsObjectUploader::Store::REMOTE) }
validates :oid, presence: true, uniqueness: true
......
......
......@@ -273,7 +273,6 @@ class Project < ApplicationRecord
has_many :builds, class_name: 'Ci::Build', inverse_of: :project, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :build_trace_section_names, class_name: 'Ci::BuildTraceSectionName'
has_many :build_trace_chunks, class_name: 'Ci::BuildTraceChunk', through: :builds, source: :trace_chunks
has_many :job_artifacts, class_name: 'Ci::JobArtifact'
has_many :runner_projects, class_name: 'Ci::RunnerProject', inverse_of: :project
has_many :runners, through: :runner_projects, source: :runner, class_name: 'Ci::Runner'
has_many :variables, class_name: 'Ci::Variable'
......
......
......@@ -298,7 +298,7 @@ class JiraService < IssueTrackerService
title: title,
status: status,
icon: {
title: 'GitLab', url16x16: asset_url(Gitlab::Favicon.main, host: gitlab_config.base_url)
title: 'GitLab', url16x16: asset_url(Gitlab::Favicon.main, host: gitlab_config.url)
}
}
}
......
......
......@@ -22,6 +22,7 @@ class Release < ApplicationRecord
accepts_nested_attributes_for :links, allow_destroy: true
validates :description, :project, :tag, presence: true
validates :name, presence: true, on: :create
validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") }
scope :sorted, -> { order(released_at: :desc) }
......
......
......@@ -133,28 +133,18 @@ class Repository
end
end
# the opts are:
# - :path
# - :limit
# - :offset
# - :skip_merges
# - :after
# - :before
# - :all
# - :first_parent
def commits(ref = nil, opts = {})
def commits(ref = nil, path: nil, limit: nil, offset: nil, skip_merges: false, after: nil, before: nil, all: nil)
options = {
repo: raw_repository,
ref: ref,
path: opts[:path],
follow: Array(opts[:path]).length == 1,
limit: opts[:limit],
offset: opts[:offset],
skip_merges: !!opts[:skip_merges],
after: opts[:after],
before: opts[:before],
all: !!opts[:all],
first_parent: !!opts[:first_parent]
path: path,
limit: limit,
offset: offset,
after: after,
before: before,
follow: Array(path).length == 1,
skip_merges: skip_merges,
all: all
}
commits = Gitlab::Git::Commit.where(options)
......
......
......@@ -51,8 +51,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
new_file_anchor_data,
readme_anchor_data,
changelog_anchor_data,
contribution_guide_anchor_data,
gitlab_ci_anchor_data
contribution_guide_anchor_data
].compact.reject { |item| item.is_link }
end
......
......
......@@ -12,20 +12,16 @@ class ImportExportCleanUpService
def execute
Gitlab::Metrics.measure(:import_export_clean_up) do
execute_cleanup
clean_up_export_object_files
break unless File.directory?(path)
clean_up_export_files
end
end
private
def execute_cleanup
clean_up_export_object_files
ensure
# We don't want a failure in cleaning up object storage from
# blocking us from cleaning up temporary storage.
clean_up_export_files if File.directory?(path)
end
def clean_up_export_files
Gitlab::Popen.popen(%W(find #{path} -not -path #{path} -mmin +#{mmin} -delete))
end
......
......
......@@ -40,7 +40,7 @@ module Projects
return unless tags.count == other_tags.count
# delete all tags
tags.map(&:unsafe_delete)
tags.map(&:delete)
end
def group_by_digest(tags)
......
......