Browse Source

Fixes #5014 - Package: File conflict with packages which include the same file location.

Rolf Schmidt 1 year ago
parent
commit
59a35379e4
2 changed files with 31 additions and 0 deletions
  1. 21 0
      app/models/package.rb
  2. 10 0
      spec/models/package_spec.rb

+ 21 - 0
app/models/package.rb

@@ -284,6 +284,8 @@ subsequently in a separate step.
           raise "Can't create file, because of not allowed file location: #{file['location']}!"
         end
 
+        ensure_no_duplicate_files!(package_db.name, file['location'])
+
         permission = file['permission'] || '644'
         content    = Base64.decode64(file['content'])
         _write_file(file['location'], permission, content)
@@ -298,6 +300,25 @@ subsequently in a separate step.
     package_db
   end
 
+  def self.ensure_no_duplicate_files!(name, location)
+    all_files.each do |check_package, check_files|
+      next if check_package == name
+      next if check_files.exclude?(location)
+
+      raise "Can't create file, because file '#{location}' is already provided by package '#{check_package}'!"
+    end
+  end
+
+  def self.all_files
+    Auth::RequestCache.fetch_value('Package/all_files') do
+      Package.all.each_with_object({}) do |package, result|
+        json_file    = Package._get_bin(package.name, package.version)
+        package_json = JSON.parse(json_file)
+        result[package.name] = package_json['files'].pluck('location')
+      end
+    end
+  end
+
 =begin
 
 reinstall package

+ 10 - 0
spec/models/package_spec.rb

@@ -314,4 +314,14 @@ RSpec.describe Package, type: :model do
       expect(File.exist?('lib/version.rb')).to be(true)
     end
   end
+
+  describe 'Package: File conflict with packages which include the same file location #5014' do
+    let(:package_1) { get_package_structure('PackageA', package_zpm_files_json, '1.0.0') }
+    let(:package_2) { get_package_structure('PackageB', package_zpm_files_json, '1.0.0') }
+
+    it 'does not allow to patch the same file twice via package' do
+      described_class.install(string: package_1)
+      expect { described_class.install(string: package_2) }.to raise_error("Can't create file, because file 'example.rb' is already provided by package 'PackageA'!")
+    end
+  end
 end