diff options
Diffstat (limited to 'app/services/packages/nuget/symbols/create_symbol_files_service.rb')
-rw-r--r-- | app/services/packages/nuget/symbols/create_symbol_files_service.rb | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/app/services/packages/nuget/symbols/create_symbol_files_service.rb b/app/services/packages/nuget/symbols/create_symbol_files_service.rb new file mode 100644 index 00000000000..03e14ba00e1 --- /dev/null +++ b/app/services/packages/nuget/symbols/create_symbol_files_service.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +module Packages + module Nuget + module Symbols + class CreateSymbolFilesService + ExtractionError = Class.new(StandardError) + SYMBOL_ENTRIES_LIMIT = 100 + CONTENT_TYPE = 'application/octet-stream' + + def initialize(package, package_zip_file) + @package = package + @symbol_entries = package_zip_file.glob('**/*.pdb') + end + + def execute + return if symbol_entries.empty? + + process_symbol_entries + rescue ExtractionError => e + Gitlab::ErrorTracking.log_exception(e, class: self.class.name, package_id: package.id) + end + + private + + attr_reader :package, :symbol_entries + + def process_symbol_entries + Tempfile.create('nuget_extraction_symbol_file') do |tmp_file| + symbol_entries.each_with_index do |entry, index| + raise ExtractionError, 'too many symbol entries' if index >= SYMBOL_ENTRIES_LIMIT + + entry.extract(tmp_file.path) { true } + File.open(tmp_file.path) do |file| + create_symbol(entry.name, file) + end + end + end + rescue Zip::EntrySizeError => e + raise ExtractionError, "symbol file has the wrong entry size: #{e.message}" + rescue Zip::EntryNameError => e + raise ExtractionError, "symbol file has the wrong entry name: #{e.message}" + end + + def create_symbol(path, file) + signature = extract_signature(file.read(1.kilobyte)) + return if signature.blank? + + ::Packages::Nuget::Symbol.create!( + package: package, + file: { tempfile: file, filename: path.downcase, content_type: CONTENT_TYPE }, + file_path: path, + signature: signature, + size: file.size + ) + rescue StandardError => e + Gitlab::ErrorTracking.log_exception(e, class: self.class.name, package_id: package.id) + end + + def extract_signature(content_fragment) + ExtractSymbolSignatureService + .new(content_fragment) + .execute + .payload + end + end + end + end +end |