162 lines
4.8 KiB
Ruby
162 lines
4.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Packages
|
|
module Debian
|
|
class ProcessPackageFileService
|
|
include ExclusiveLeaseGuard
|
|
include Gitlab::Utils::StrongMemoize
|
|
|
|
SOURCE_FIELD_SPLIT_REGEX = /[ ()]/
|
|
# used by ExclusiveLeaseGuard
|
|
DEFAULT_LEASE_TIMEOUT = 1.hour.to_i.freeze
|
|
|
|
def initialize(package_file, distribution_name, component_name)
|
|
@package_file = package_file
|
|
@distribution_name = distribution_name
|
|
@component_name = component_name
|
|
end
|
|
|
|
def execute
|
|
return if @package_file.package.pending_destruction?
|
|
|
|
validate!
|
|
|
|
try_obtain_lease do
|
|
package.transaction do
|
|
rename_package_and_set_version
|
|
update_package
|
|
update_file_metadata
|
|
cleanup_temp_package
|
|
end
|
|
|
|
::Packages::Debian::GenerateDistributionWorker.perform_async(:project, package.debian_distribution.id)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def validate!
|
|
raise ArgumentError, 'missing distribution name' unless @distribution_name.present?
|
|
raise ArgumentError, 'missing component name' unless @component_name.present?
|
|
raise ArgumentError, 'package file without Debian metadata' unless @package_file.debian_file_metadatum
|
|
raise ArgumentError, 'already processed package file' unless @package_file.debian_file_metadatum.unknown?
|
|
|
|
if file_metadata[:file_type] == :deb || file_metadata[:file_type] == :udeb || file_metadata[:file_type] == :ddeb
|
|
return
|
|
end
|
|
|
|
raise ArgumentError, "invalid package file type: #{file_metadata[:file_type]}"
|
|
end
|
|
|
|
def file_metadata
|
|
::Packages::Debian::ExtractMetadataService.new(@package_file).execute
|
|
end
|
|
strong_memoize_attr :file_metadata
|
|
|
|
def package
|
|
packages = temp_package.project
|
|
.packages
|
|
.existing_debian_packages_with(name: package_name, version: package_version)
|
|
package = packages.with_debian_codename_or_suite(@distribution_name)
|
|
.first
|
|
|
|
unless package
|
|
package_in_other_distribution = packages.first
|
|
|
|
if package_in_other_distribution
|
|
raise ArgumentError, "Debian package #{package_name} #{package_version} exists " \
|
|
"in distribution #{package_in_other_distribution.debian_distribution.codename}"
|
|
end
|
|
end
|
|
|
|
package || temp_package
|
|
end
|
|
strong_memoize_attr :package
|
|
|
|
def temp_package
|
|
@package_file.package
|
|
end
|
|
strong_memoize_attr :temp_package
|
|
|
|
def package_name
|
|
package_name_and_version[0]
|
|
end
|
|
|
|
def package_version
|
|
package_name_and_version[1]
|
|
end
|
|
|
|
def package_name_and_version
|
|
package_name = file_metadata[:fields]['Package']
|
|
package_version = file_metadata[:fields]['Version']
|
|
|
|
if file_metadata[:fields]['Source']
|
|
# "sample" or "sample (1.2.3~alpha2)"
|
|
source_field_parts = file_metadata[:fields]['Source'].split(SOURCE_FIELD_SPLIT_REGEX)
|
|
package_name = source_field_parts[0]
|
|
package_version = source_field_parts[2] || package_version
|
|
end
|
|
|
|
[package_name, package_version]
|
|
end
|
|
strong_memoize_attr :package_name_and_version
|
|
|
|
def rename_package_and_set_version
|
|
package.update!(
|
|
name: package_name,
|
|
version: package_version,
|
|
status: :default
|
|
)
|
|
end
|
|
|
|
def update_package
|
|
return unless using_temporary_package?
|
|
|
|
package.update!(
|
|
debian_publication_attributes: { distribution_id: distribution.id }
|
|
)
|
|
end
|
|
|
|
def using_temporary_package?
|
|
package.id == temp_package.id
|
|
end
|
|
|
|
def distribution
|
|
Packages::Debian::DistributionsFinder.new(
|
|
@package_file.package.project,
|
|
codename_or_suite: @distribution_name
|
|
).execute.last!
|
|
end
|
|
strong_memoize_attr :distribution
|
|
|
|
def update_file_metadata
|
|
::Packages::UpdatePackageFileService.new(@package_file, package_id: package.id)
|
|
.execute
|
|
|
|
# Force reload from database, as package has changed
|
|
@package_file.reload_package
|
|
|
|
@package_file.debian_file_metadatum.update!(
|
|
file_type: file_metadata[:file_type],
|
|
component: @component_name,
|
|
architecture: file_metadata[:architecture],
|
|
fields: file_metadata[:fields]
|
|
)
|
|
end
|
|
|
|
def cleanup_temp_package
|
|
temp_package.destroy unless using_temporary_package?
|
|
end
|
|
|
|
# used by ExclusiveLeaseGuard
|
|
def lease_key
|
|
"packages:debian:process_package_file_service:package_file:#{@package_file.id}"
|
|
end
|
|
|
|
# used by ExclusiveLeaseGuard
|
|
def lease_timeout
|
|
DEFAULT_LEASE_TIMEOUT
|
|
end
|
|
end
|
|
end
|
|
end
|