Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package yast2-storage-ng for 
openSUSE:Factory checked in at 2024-09-22 11:05:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yast2-storage-ng (Old)
 and      /work/SRC/openSUSE:Factory/.yast2-storage-ng.new.29891 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yast2-storage-ng"

Sun Sep 22 11:05:52 2024 rev:163 rq:1202231 version:5.0.18

Changes:
--------
--- /work/SRC/openSUSE:Factory/yast2-storage-ng/yast2-storage-ng.changes        
2024-08-27 19:38:34.838560960 +0200
+++ 
/work/SRC/openSUSE:Factory/.yast2-storage-ng.new.29891/yast2-storage-ng.changes 
    2024-09-22 11:06:05.784791139 +0200
@@ -1,0 +2,7 @@
+Fri Sep 20 13:06:00 UTC 2024 - Ancor Gonzalez Sosa <an...@suse.com>
+
+- Extend the API to resize partitions during a proposal (required
+  by gh#openSUSE/agama#1599).
+- 5.0.18
+
+-------------------------------------------------------------------

Old:
----
  yast2-storage-ng-5.0.17.tar.bz2

New:
----
  yast2-storage-ng-5.0.18.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yast2-storage-ng.spec ++++++
--- /var/tmp/diff_new_pack.ywyuRT/_old  2024-09-22 11:06:06.244810140 +0200
+++ /var/tmp/diff_new_pack.ywyuRT/_new  2024-09-22 11:06:06.244810140 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-storage-ng
-Version:        5.0.17
+Version:        5.0.18
 Release:        0
 Summary:        YaST2 - Storage Configuration
 License:        GPL-2.0-only OR GPL-3.0-only

++++++ yast2-storage-ng-5.0.17.tar.bz2 -> yast2-storage-ng-5.0.18.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/package/yast2-storage-ng.changes 
new/yast2-storage-ng-5.0.18/package/yast2-storage-ng.changes
--- old/yast2-storage-ng-5.0.17/package/yast2-storage-ng.changes        
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/package/yast2-storage-ng.changes        
2024-09-20 15:57:19.000000000 +0200
@@ -1,4 +1,11 @@
 -------------------------------------------------------------------
+Fri Sep 20 13:06:00 UTC 2024 - Ancor Gonzalez Sosa <an...@suse.com>
+
+- Extend the API to resize partitions during a proposal (required
+  by gh#openSUSE/agama#1599).
+- 5.0.18
+
+-------------------------------------------------------------------
 Mon Aug 26 14:47:40 UTC 2024 - José Iván López González <jlo...@suse.com>
 
 - AutoYaST: small fix to ensure symbol for the drive type when
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/package/yast2-storage-ng.spec 
new/yast2-storage-ng-5.0.18/package/yast2-storage-ng.spec
--- old/yast2-storage-ng-5.0.17/package/yast2-storage-ng.spec   2024-08-26 
17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/package/yast2-storage-ng.spec   2024-09-20 
15:57:19.000000000 +0200
@@ -16,7 +16,7 @@
 #
 
 Name:           yast2-storage-ng
-Version:        5.0.17
+Version:        5.0.18
 Release:        0
 Summary:        YaST2 - Storage Configuration
 License:        GPL-2.0-only OR GPL-3.0-only
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/free_disk_space.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/free_disk_space.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/free_disk_space.rb    
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/free_disk_space.rb    
2024-09-20 15:57:19.000000000 +0200
@@ -95,6 +95,10 @@
 
     # Whether the region belongs to a partition that is going to be reused
     #
+    # This only makes sense in the case of DASD devices with an implicit 
partition table,
+    # partitions are never deleted there, but 'reused' (nothing to do with the 
'reuse' flag of
+    # planned devices).
+    #
     # @return [Boolean]
     def reused_partition?
       return false if growing?
@@ -141,6 +145,26 @@
       @require_end_alignment ||= disk.as_not_empty { 
disk.partition_table.require_end_alignment? }
     end
 
+    # Finds the remaining free space within the scope of the disk chunk 
defined by
+    # this (possibly outdated) FreeDiskSpace object
+    #
+    # @raise [NoDiskSpaceError] if there is no free space in the devicegraph 
at the region
+    #   defined by the current FreeDiskSpace object
+    #
+    # @param devicegraph [Devicegraph]
+    # @return [FreeDiskSpace] free space within the area of the original 
FreeDiskSpace object
+    def updated_free_space(devicegraph)
+      disk = devicegraph.blk_devices.detect { |d| d.name == disk_name }
+      spaces = disk.as_not_empty { disk.free_spaces }.select do |space|
+        space.region.start >= region.start &&
+          space.region.start < region.end
+      end
+      raise NoDiskSpaceError, "Exhausted free space" if spaces.empty?
+
+      spaces.first
+    end
+
+    # @return [String]
     def to_s
       "#<FreeDiskSpace disk_name=#{disk_name}, size=#{disk_size}, 
start_offset=#{start_offset}>"
     end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/partition.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/partition.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/partition.rb  2024-08-26 
17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/partition.rb  2024-09-20 
15:57:19.000000000 +0200
@@ -281,6 +281,25 @@
       !disk.nil? && type.is?(:primary) && id.is?(:windows_system)
     end
 
+    # Whether the given disk space is located right after this partition
+    #
+    # @param disk_space [FreeDiskSpace]
+    # @return [Boolean]
+    def subsequent_slot?(disk_space)
+      return false if disk_space.disk != partition_table.partitionable
+      return false unless disk_space.region.start > region.end
+
+      # The simplest case can be easily evaluated
+      return true if disk_space.region.start == (region.end + 1)
+
+      # But if the end of the partition is not properly aligned, we may need 
to look closer
+      # FIXME: this can likely be both simpler and more efficient. But since 
it's used
+      # only for missaligned partitions is not a priority
+      slots = partition_table.partitions + 
partition_table.unused_partition_slots
+      break_points = slots.flat_map { |s| [s.region.start, s.region.end] }
+      break_points.none? { |p| p > region.end && p < disk_space.region.start }
+    end
+
     protected
 
     # Values for volume specification matching
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/planned/assigned_space.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/planned/assigned_space.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/planned/assigned_space.rb     
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/planned/assigned_space.rb     
2024-09-20 15:57:19.000000000 +0200
@@ -161,6 +161,15 @@
         end
       end
 
+      # Space that can be sustracted from the start of the region without 
invalidating this
+      # valid assignation
+      #
+      # @return [DiskSize]
+      def disposable_size
+        # FIXME: This is more based on trial and error than on a real rationale
+        usable_extra_size - align_grain
+      end
+
       # Space consumed by the EBR of one logical partition in a given disk
       # See https://en.wikipedia.org/wiki/Extended_boot_record
       #
@@ -208,6 +217,14 @@
         @disk_size ||= @disk_space.disk_size
       end
 
+      # Recalculates the information about the available space, in case it has 
been modified
+      def update_disk_space
+        @region = nil
+        @disk_size = nil
+        @space_start = nil
+        @disk_space = @disk_space.updated_free_space(devicegraph)
+      end
+
       protected
 
       # Checks whether the disk space is inside an extended partition
@@ -324,6 +341,11 @@
         end
       end
 
+      # @return [Devicegraph] devicegraph in which the space is defined
+      def devicegraph
+        disk_space.disk.devicegraph
+      end
+
       def partitions_sorted_by_attr(*attrs, nils_first: false, descending: 
false)
         partitions.each_with_index.sort do |one, other|
           compare(one, other, attrs, nils_first, descending)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/planned/can_be_resized.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/planned/can_be_resized.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/planned/can_be_resized.rb     
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/planned/can_be_resized.rb     
2024-09-20 15:57:19.000000000 +0200
@@ -44,6 +44,15 @@
         max_size <= device_to_reuse(devicegraph).size
       end
 
+      # Limit the max size to ensure the device does not grow more than a give 
margin
+      #
+      # @param max_grow [DiskSize] max margin to grow the device
+      # @param devicegraph [Devicegraph]
+      def limit_grow(max_grow, devicegraph)
+        limit = device_to_reuse(devicegraph).size + max_grow
+        self.max_size = [max_size, limit].min
+      end
+
       protected
 
       # Implements reuse_device! hook
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/planned/has_size.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/planned/has_size.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/planned/has_size.rb   
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/planned/has_size.rb   
2024-09-20 15:57:19.000000000 +0200
@@ -200,7 +200,7 @@
           devices.map(&:weight).reduce(0, :+)
         end
 
-        # Checks if there are eough space at all
+        # Checks if there are enough space at all
         # @raise RuntimeError if there is not enough space
         def check_size(devices, space_size)
           needed_size = DiskSize.sum(devices.map(&:min))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/planned/partition.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/planned/partition.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/planned/partition.rb  
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/planned/partition.rb  
2024-09-20 15:57:19.000000000 +0200
@@ -87,6 +87,19 @@
         @primary = false
       end
 
+      # Whether this corresponds to a reused partition that is located right 
before the given
+      # assigned space
+      #
+      # @param assigned_space [AssignedSpace]
+      # @return [Boolean]
+      def subsequent_slot?(assigned_space)
+        devicegraph = assigned_space.disk_space.disk.devicegraph
+        dev = device_to_reuse(devicegraph)
+        return false unless dev
+
+        dev.subsequent_slot?(assigned_space.disk_space)
+      end
+
       def self.to_string_attrs
         [
           :mount_point, :reuse_name, :reuse_sid, :min_size, :max_size,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/proposal/partition_creator.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/proposal/partition_creator.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/proposal/partition_creator.rb 
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/proposal/partition_creator.rb 
2024-09-20 15:57:19.000000000 +0200
@@ -104,7 +104,7 @@
         devices_map = {}
         planned_partitions.each_with_index do |part, idx|
 
-          space = free_space_within(initial_free_space)
+          space = initial_free_space.updated_free_space(devicegraph)
           primary = planned_partitions.size - idx > num_logical
           partition = create_partition(part, space, primary)
           part.format!(partition)
@@ -117,22 +117,6 @@
         devices_map
       end
 
-      # Finds the remaining free space within the scope of the disk chunk
-      # defined by a (probably outdated) FreeDiskSpace object
-      #
-      # @param initial_free_space [FreeDiskSpace] the original disk chunk, the
-      #   returned free space will be within this area
-      def free_space_within(initial_free_space)
-        disk = devicegraph.blk_devices.detect { |d| d.name == 
initial_free_space.disk_name }
-        spaces = disk.as_not_empty { disk.free_spaces }.select do |space|
-          space.region.start >= initial_free_space.region.start &&
-            space.region.start < initial_free_space.region.end
-        end
-        raise NoDiskSpaceError, "Exhausted free space" if spaces.empty?
-
-        spaces.first
-      end
-
       # Create a real partition for the specified planned partition within the
       # specified slot of free space.
       #
@@ -150,7 +134,7 @@
           create_primary_partition(planned_partition, free_space)
         elsif !ptable.has_extended?
           create_extended_partition(free_space)
-          free_space = free_space_within(free_space)
+          free_space = free_space.updated_free_space(devicegraph)
           create_logical_partition(planned_partition, free_space)
         else
           create_logical_partition(planned_partition, free_space)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/proposal/space_maker.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/proposal/space_maker.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/proposal/space_maker.rb       
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/proposal/space_maker.rb       
2024-09-20 15:57:19.000000000 +0200
@@ -361,14 +361,17 @@
       def execute_shrink(action, devicegraph, planned_partitions, disk_name)
         log.info "SpaceMaker#execute_shrink - #{action}"
 
-        if action.shrink_size.nil?
+        if action.target_size.nil?
+          part = devicegraph.find_device(action.sid)
           if planned_partitions
-            part = devicegraph.find_device(action.sid)
-            action.shrink_size = resizing_size(part, planned_partitions, 
disk_name)
+            resizing = resizing_size(part, planned_partitions, disk_name)
+            action.target_size = resizing > part.size ? DiskSize.zero : 
part.size - resizing
           else
-            action.shrink_size = DiskSize.Unlimited
+            # Mandatory resize
+            action.target_size = part.size
           end
         end
+
         action.shrink(devicegraph)
       end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/proposal/space_maker_actions/bigger_resize_strategy.rb
 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/proposal/space_maker_actions/bigger_resize_strategy.rb
--- 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/proposal/space_maker_actions/bigger_resize_strategy.rb
        2024-08-26 17:03:52.000000000 +0200
+++ 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/proposal/space_maker_actions/bigger_resize_strategy.rb
        2024-09-20 15:57:19.000000000 +0200
@@ -35,34 +35,29 @@
           @to_delete_mandatory = []
           @to_delete_optional = []
           @to_wipe = []
-          @to_resize = []
+          @to_shrink_mandatory = []
+          @to_shrink_optional = []
         end
 
         # @param disk [Disk] see {List}
         def add_mandatory_actions(disk)
           return unless disk.partition_table?
 
-          devices = partitions(disk).select { |p| configured?(p, 
:force_delete) }
-          to_delete_mandatory.concat(devices)
+          add_mandatory_delete(disk)
+          add_mandatory_shrink(disk)
         end
 
         # @param disk [Disk] see {List}
         def add_optional_actions(disk, _lvm_helper)
           add_wipe(disk)
-          add_resize(disk)
+          add_optional_shrink(disk)
           add_optional_delete(disk)
         end
 
         # @return [Action, nil] nil if there are no more actions in the list
         def next
           source = source_for_next
-          dev = send(source).first
-          return unless dev
-
-          return Shrink.new(dev) if source == :to_resize
-          return Wipe.new(dev) if source == :to_wipe
-
-          Delete.new(dev, related_partitions: false)
+          send(source).first
         end
 
         # @param deleted_sids [Array<Integer>] see {List}
@@ -70,7 +65,8 @@
           send(source_for_next).shift
           cleanup(to_delete_mandatory, deleted_sids)
           cleanup(to_delete_optional, deleted_sids)
-          cleanup(to_resize, deleted_sids)
+          cleanup(to_shrink_mandatory, deleted_sids)
+          cleanup(to_shrink_optional, deleted_sids)
         end
 
         private
@@ -78,16 +74,19 @@
         # @return [ProposalSpaceSettings] proposal settings for making space
         attr_reader :settings
 
-        # @return [Array<BlkDevice>] list of devices to be deleted (mandatory)
+        # @return [Array<Base>] list of mandatory delete actions
         attr_reader :to_delete_mandatory
 
-        # @return [Array<BlkDevice>] list of devices to be deleted (optionally)
+        # @return [Array<Base>] list of optional delete actions
         attr_reader :to_delete_optional
 
-        # @return [Array<Partition>] list of partitions to be shrunk
-        attr_reader :to_resize
+        # @return [Array<Base>] list of mandatory shrink actions
+        attr_reader :to_shrink_mandatory
+
+        # @return [Array<Base>] list of optional shrink actions
+        attr_reader :to_shrink_optional
 
-        # @return [Array<BlkDevice>] list of disks to be emptied if needed
+        # @return [Array<Base>] list of actions to wipe disks if needed
         attr_reader :to_wipe
 
         # @see #add_optional_actions
@@ -95,32 +94,60 @@
         def add_wipe(disk)
           return if disk.partition_table?
 
-          to_wipe << disk
+          to_wipe << Wipe.new(disk)
         end
 
         # @see #add_optional_actions
         # @param disk [Disk]
-        def add_resize(disk)
+        def add_optional_shrink(disk)
           return unless disk.partition_table?
 
-          partitions = partitions(disk).select { |p| configured?(p, :resize) }
-          return if partitions.empty?
+          actions = optional_shrinks(disk)
+          return if actions.empty?
 
-          @to_resize = (to_resize + partitions).sort { |a, b| 
preferred_resize(a, b) }
+          @to_shrink_optional = (to_shrink_optional + actions).sort do |a, b|
+            preferred_resize(a, b, disk.devicegraph)
+          end
         end
 
-        # Compares two partitions to decide which one should be resized first
-        #
-        # @param part1 [Partition]
-        # @param part2 [Partition]
-        def preferred_resize(part1, part2)
-          result = part2.recoverable_size <=> part1.recoverable_size
+        # @see #add_optional_shrink
+        # @param disk [Disk]
+        def optional_shrinks(disk)
+          partitions(disk).map do |part|
+            resize = resize_actions.find { |a| a.device == part.name }
+            next unless resize
+            next if resize.min_size && resize.min_size > part.size
+            next if resize.max_size && resize.max_size < part.size
+
+            resize_to_shrink(part, resize)
+          end.compact
+        end
+
+        # Compares two shrinking operations to decide which one should be 
executed first
+        #
+        # @param resize1 [Shrink]
+        # @param resize2 [Shrink]
+        def preferred_resize(resize1, resize2, devicegraph)
+          part1 = devicegraph.find_device(resize1.sid)
+          part2 = devicegraph.find_device(resize2.sid)
+          result = recoverable_size(part2, resize2) <=> 
recoverable_size(part1, resize1)
           return result unless result.zero?
 
           # Just to ensure stable sorting between different executions in case 
of draw
           part1.name <=> part2.name
         end
 
+        # Max space that can be recovered from the given partition, having 
into account the
+        # restrictions imposed by the its Resize action
+        #
+        # @see #preferred_resize
+        def recoverable_size(partition, resize)
+          min = resize.min_size
+          return partition.recoverable_size if min.nil? || min > partition.size
+
+          [partition.recoverable_size, partition.size - min].min
+        end
+
         # @see #add_optional_actions
         #
         # @param disk [Disk]
@@ -128,7 +155,9 @@
           return unless disk.partition_table?
 
           partitions = partitions(disk).select { |p| configured?(p, :delete) }
-          to_delete_optional.concat(partitions.sort { |a, b| 
preferred_delete(a, b) })
+          partitions.sort! { |a, b| preferred_delete(a, b) }
+          actions = partitions.map { |p| Delete.new(p, related_partitions: 
false) }
+          to_delete_optional.concat(actions)
         end
 
         # Compares two partitions to decide which one should be deleted first
@@ -136,10 +165,36 @@
         # @param part1 [Partition]
         # @param part2 [Partition]
         def preferred_delete(part1, part2)
-          # Mimic order from the auto strategy. We might consider other 
approaches in the future.
+          # FIXME: Currently this mimics the order from the auto strategy.
+          # We might consider other approaches in the future, like deleting 
partitions that are
+          # next to another partition that needs to grow. That circumstance is 
maybe not so easy
+          # to evaluate at the start and needs to be reconsidered after every 
action.
           part2.region.start <=> part1.region.start
         end
 
+        # @see #add_optional_actions
+        # @param disk [Disk]
+        def add_mandatory_shrink(disk)
+          shrink_actions = partitions(disk).map do |part|
+            resize = resize_actions.find { |a| a.device == part.name }
+            next unless resize
+            next unless resize.max_size
+            next if part.size <= resize.max_size
+
+            resize_to_shrink(part, resize)
+          end.compact
+
+          to_shrink_mandatory.concat(shrink_actions)
+        end
+
+        # @see #add_mandatory_actions
+        # @param disk [Disk]
+        def add_mandatory_delete(disk)
+          devices = partitions(disk).select { |p| configured?(p, 
:force_delete) }
+          actions = devices.map { |d| Delete.new(d, related_partitions: false) 
}
+          to_delete_mandatory.concat(actions)
+        end
+
         # Whether the given action is configured for the given device at the 
proposal settings
         #
         # @see ProposalSpaceSettings#actions
@@ -148,12 +203,17 @@
         # @param action [Symbol] :force_delete, :delete or :resize
         # @return [Boolean]
         def configured?(device, action)
-          settings.actions[device.name]&.to_sym == action
+          case action
+          when :force_delete
+            delete_actions.select(&:mandatory).any? { |a| a.device == 
device.name }
+          when :delete
+            delete_actions.reject(&:mandatory).any? { |a| a.device == 
device.name }
+          end
         end
 
         # Removes devices with the given sids from a collection
         #
-        # @param collection [Array<BlkDevice>]
+        # @param collection [Array<Action>]
         # @param deleted_sids [Array<Integer>]
         def cleanup(collection, deleted_sids)
           collection.delete_if { |d| deleted_sids.include?(d.sid) }
@@ -167,8 +227,10 @@
             :to_delete_mandatory
           elsif to_wipe.any?
             :to_wipe
-          elsif to_resize.any?
-            :to_resize
+          elsif to_shrink_mandatory.any?
+            :to_shrink_mandatory
+          elsif to_shrink_optional.any?
+            :to_shrink_optional
           else
             :to_delete_optional
           end
@@ -178,6 +240,24 @@
         def partitions(disk)
           disk.partitions.reject { |part| part.type.is?(:extended) }
         end
+
+        # Trivial conversion
+        def resize_to_shrink(partition, resize)
+          Shrink.new(partition).tap do |shrink|
+            shrink.min_size = resize.min_size
+            shrink.max_size = resize.max_size
+          end
+        end
+
+        # All delete actions from the settings
+        def delete_actions
+          settings.actions.select { |a| a.is?(:delete) }
+        end
+
+        # All resize actions from the settings
+        def resize_actions
+          settings.actions.select { |a| a.is?(:resize) }
+        end
       end
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/proposal/space_maker_actions/shrink.rb
 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/proposal/space_maker_actions/shrink.rb
--- 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/proposal/space_maker_actions/shrink.rb
        2024-08-26 17:03:52.000000000 +0200
+++ 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/proposal/space_maker_actions/shrink.rb
        2024-09-20 15:57:19.000000000 +0200
@@ -26,12 +26,25 @@
       #
       # @see Base
       class Shrink < Base
-        # @return [DiskSize] size of the space to substract ideally
-        attr_accessor :shrink_size
+        # Minimal size of the device set by the configuration, regardless of 
the ResizeInfo
+        #
+        # If set to nil, there is no artificial limit
+        # @return [DiskSize, nil]
+        attr_accessor :min_size
+
+        # Max size of the device set by the configuration, regardless of the 
ResizeInfo
+        #
+        # If set to nil, there is no artificial limit
+        # @return [DiskSize, nil]
+        attr_accessor :max_size
+
+        # Ideal final size of the device to satisfy the SpaceMaker algorithm
+        # @return [DiskSize]
+        attr_accessor :target_size
 
         # Reduces the size of the target partition
         #
-        # If possible, it reduces the size of the partition by {#shrink_size}.
+        # If possible, it reduces the size of the partition to 
{#adjusted_target_size}.
         # Otherwise, it reduces the size as much as possible.
         #
         # This method does not take alignment into account.
@@ -48,9 +61,21 @@
 
         # @param partition [Partition]
         def shrink_partition(partition)
-          target = shrink_size.unlimited? ? DiskSize.zero : partition.size - 
shrink_size
           # Explicitly avoid alignment to keep current behavior (to be 
reconsidered)
-          partition.resize(target, align_type: nil)
+          partition.resize(adjusted_target_size, align_type: nil)
+        end
+
+        # Real target size taking into account the max and min limits
+        #
+        # @return [DiskSize]
+        def adjusted_target_size
+          if min_size && min_size > target_size
+            min_size
+          elsif max_size && max_size < target_size
+            max_size
+          else
+            target_size
+          end
         end
       end
     end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/proposal_space_settings.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/proposal_space_settings.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/proposal_space_settings.rb    
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/proposal_space_settings.rb    
2024-09-20 15:57:19.000000000 +0200
@@ -19,6 +19,7 @@
 
 require "yast"
 require "y2storage/equal_by_instance_variables"
+require "y2storage/space_actions"
 
 module Y2Storage
   # Class to encapsulate all the GuidedProposal settings related to the 
process of making space
@@ -84,27 +85,20 @@
 
     # What to do with existing partitions if they are involved in the process 
of making space.
     #
-    # Keys are device names (like in BlkDevice#name, no alternative names) 
that correspond to a
-    # partition.
-    #
-    # The value for each key specifies what to do with the corresponding 
partition if the storage
-    # proposal needs to process the corresponding disk. If the device is not 
explicitly mentioned,
-    # nothing will be done. Possible values are :resize, :delete and 
:force_delete.
-    #
     # Entries for devices that are not involved in the proposal are ignored. 
For example, if all
     # the volumes are configured to be placed at /dev/sda but there is an 
entry like
-    # `{"/dev/sdb1" => :force_delete}`, the corresponding /dev/sdb1 partition 
will NOT be deleted
-    # because there is no reason for the proposal to process the disk /dev/sdb.
+    # Delete<device: "/dev/sdb1", mandatory: true>, the corresponding 
/dev/sdb1 partition will NOT
+    # be deleted because there is no reason for the proposal to process the 
disk /dev/sdb.
     #
     # Device names corresponding to extended partitions are also ignored. The 
storage proposal only
     # considers actions for primary and logical partitions.
     #
-    # @return [Hash{String => Symbol}]
+    # @return [Array<SpaceActions::Base>]
     attr_accessor :actions
 
     def initialize
       @strategy = :auto
-      @actions = {}
+      @actions = []
     end
 
     # Whether the settings disable deletion of a given type of partitions
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/space_actions/base.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/space_actions/base.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/space_actions/base.rb 
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/space_actions/base.rb 
2024-09-20 15:57:19.000000000 +0200
@@ -0,0 +1,46 @@
+# Copyright (c) [2024] SUSE LLC
+#
+# All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, contact SUSE LLC.
+#
+# To contact SUSE LLC about this file by physical or electronic mail, you may
+# find current contact information at www.suse.com.
+
+require "y2storage/equal_by_instance_variables"
+
+module Y2Storage
+  module SpaceActions
+    # Base class for representing the actions of the bigger_resize SpaceMaker 
strategy
+    class Base
+      include EqualByInstanceVariables
+      attr_reader :device
+
+      # Constructor
+      def initialize(device)
+        @device = device
+      end
+
+      # Checks whether this is a concrete kind(s) of action
+      # @return [Boolean]
+      def is?(*types)
+        (types.map(&:to_sym) & types_for_is).any?
+      end
+
+      # @see #is?
+      def types_for_is
+        []
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/space_actions/delete.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/space_actions/delete.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/space_actions/delete.rb       
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/space_actions/delete.rb       
2024-09-20 15:57:19.000000000 +0200
@@ -0,0 +1,42 @@
+# Copyright (c) [2024] SUSE LLC
+#
+# All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, contact SUSE LLC.
+#
+# To contact SUSE LLC about this file by physical or electronic mail, you may
+# find current contact information at www.suse.com.
+
+require "y2storage/space_actions/base"
+
+module Y2Storage
+  module SpaceActions
+    # Delete action to configure the bigger_resize SpaceMaker strategy
+    class Delete < Base
+      # Whether the delete action must always be executed (if the involved 
disk is processed)
+      # @return [Boolean]
+      attr_reader :mandatory
+
+      # Constructor
+      def initialize(device, mandatory: false)
+        super(device)
+        @mandatory = mandatory
+      end
+
+      # @see #is?
+      def types_for_is
+        [:delete]
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/space_actions/resize.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/space_actions/resize.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/space_actions/resize.rb       
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/space_actions/resize.rb       
2024-09-20 15:57:19.000000000 +0200
@@ -0,0 +1,53 @@
+# Copyright (c) [2024] SUSE LLC
+#
+# All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, contact SUSE LLC.
+#
+# To contact SUSE LLC about this file by physical or electronic mail, you may
+# find current contact information at www.suse.com.
+
+require "y2storage/space_actions/base"
+
+module Y2Storage
+  module SpaceActions
+    # Resize action to configure the bigger_resize SpaceMaker strategy
+    class Resize < Base
+      # Min size the device should have.
+      #
+      # Nil is equivalent to the initial size of the device (no shrinking, 
only growing).
+      #
+      # @return [DiskSize, nil]
+      attr_reader :min_size
+
+      # Max size the device should have.
+      #
+      # Nil is equivalent to the initial size of the device (no growing, only 
shrinking).
+      #
+      # @return [DiskSize, nil]
+      attr_reader :max_size
+
+      # Constructor
+      def initialize(device, min_size: DiskSize.zero, max_size: nil)
+        super(device)
+        @min_size = min_size
+        @max_size = max_size
+      end
+
+      # @see #is?
+      def types_for_is
+        [:resize]
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/src/lib/y2storage/space_actions.rb 
new/yast2-storage-ng-5.0.18/src/lib/y2storage/space_actions.rb
--- old/yast2-storage-ng-5.0.17/src/lib/y2storage/space_actions.rb      
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-storage-ng-5.0.18/src/lib/y2storage/space_actions.rb      
2024-09-20 15:57:19.000000000 +0200
@@ -0,0 +1,27 @@
+# Copyright (c) [2024] SUSE LLC
+#
+# All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, contact SUSE LLC.
+#
+# To contact SUSE LLC about this file by physical or electronic mail, you may
+# find current contact information at www.suse.com.
+
+module Y2Storage
+  # Namespace for the objects representing the actions of the bigger_resize 
SpaceMaker strategy
+  module SpaceActions
+  end
+end
+
+require "y2storage/space_actions/delete"
+require "y2storage/space_actions/resize"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/test/y2storage/partition_test.rb 
new/yast2-storage-ng-5.0.18/test/y2storage/partition_test.rb
--- old/yast2-storage-ng-5.0.17/test/y2storage/partition_test.rb        
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/test/y2storage/partition_test.rb        
2024-09-20 15:57:19.000000000 +0200
@@ -446,6 +446,55 @@
     end
   end
 
+  describe "#subsequent_slot?" do
+    let(:disk) { fake_devicegraph.find_by_name(disk_name) }
+    let(:region) { disk.partition_table.unused_partition_slots[slot].region }
+    let(:slot) { 0 }
+    let(:space) { Y2Storage::FreeDiskSpace.new(disk, region) }
+    subject(:partition) { fake_devicegraph.find_by_name(part_name) }
+
+    context "when the space starts at the sector right after the partition" do
+      let(:scenario) { "spaces_5_5_10" }
+      let(:part_name) { "/dev/sda1" }
+      let(:disk_name) { "/dev/sda" }
+
+      it "returns true" do
+        expect(partition.subsequent_slot?(space)).to eq true
+      end
+    end
+
+    context "when the space is right after a partition with missaligned end" do
+      let(:scenario) { "alignment" }
+      let(:part_name) { "/dev/sdb1" }
+      let(:disk_name) { "/dev/sdb" }
+
+      it "returns true" do
+        expect(partition.subsequent_slot?(space)).to eq true
+      end
+    end
+
+    context "when the space is not adyacent to the partition" do
+      let(:scenario) { "spaces_5_5_10" }
+      let(:part_name) { "/dev/sda1" }
+      let(:disk_name) { "/dev/sda" }
+      let(:slot) { 1 }
+
+      it "returns false" do
+        expect(partition.subsequent_slot?(space)).to eq false
+      end
+    end
+
+    context "when the space starts at an appropriate sector but is in another 
disk" do
+      let(:scenario) { "alignment" }
+      let(:part_name) { "/dev/sdb1" }
+      let(:disk_name) { "/dev/sdc" }
+
+      it "returns false" do
+        expect(partition.subsequent_slot?(space)).to eq false
+      end
+    end
+  end
+
   # Only basic cases are tested here. More exhaustive tests can be found in 
tests
   # for Y2Storage::MatchVolumeSpec
   describe "#match_volume?" do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/test/y2storage/planned/assigned_space_test.rb 
new/yast2-storage-ng-5.0.18/test/y2storage/planned/assigned_space_test.rb
--- old/yast2-storage-ng-5.0.17/test/y2storage/planned/assigned_space_test.rb   
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/test/y2storage/planned/assigned_space_test.rb   
2024-09-20 15:57:19.000000000 +0200
@@ -179,4 +179,25 @@
       end
     end
   end
+
+  describe "#update_disk_space" do
+    before { fake_scenario("mixed_disks") }
+    let(:disk) { fake_devicegraph.find_by_name("/dev/sda") }
+    subject(:assigned) { described_class.new(disk.free_spaces.first, []) }
+
+    it "refreshes all the information related to the available space" do
+      expect(assigned.region.start).to eq 209717248
+      expect(assigned.disk_size).to eq 2.GiB
+
+      disk.partition_table.create_partition(
+        "/dev/sda3",
+        Y2Storage::Region.create(assigned.region.start, 1048576, 512),
+        Y2Storage::PartitionType::PRIMARY
+      )
+      assigned.update_disk_space
+
+      expect(assigned.region.start).to eq(209717248 + 1048576)
+      expect(assigned.disk_size).to eq 1.5.GiB
+    end
+  end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/test/y2storage/planned/can_be_resized_test.rb 
new/yast2-storage-ng-5.0.18/test/y2storage/planned/can_be_resized_test.rb
--- old/yast2-storage-ng-5.0.17/test/y2storage/planned/can_be_resized_test.rb   
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/test/y2storage/planned/can_be_resized_test.rb   
2024-09-20 15:57:19.000000000 +0200
@@ -172,4 +172,18 @@
       end
     end
   end
+
+  describe "#limit_grow" do
+    before { planned.max_size = 70.GiB }
+
+    it "limits the max size if the sum of the new limit and the original size 
is smaller" do
+      planned.limit_grow(5.GiB, devicegraph)
+      expect(planned.max_size).to eq 55.GiB
+    end
+
+    it "leaves the max size untouched if the sum of original size and limit is 
bigger" do
+      planned.limit_grow(50.GiB, devicegraph)
+      expect(planned.max_size).to eq 70.GiB
+    end
+  end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/test/y2storage/planned/partition_test.rb 
new/yast2-storage-ng-5.0.18/test/y2storage/planned/partition_test.rb
--- old/yast2-storage-ng-5.0.17/test/y2storage/planned/partition_test.rb        
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/test/y2storage/planned/partition_test.rb        
2024-09-20 15:57:19.000000000 +0200
@@ -111,4 +111,53 @@
       end
     end
   end
+
+  describe "#subsequent_slot?" do
+    let(:assigned_space) { Y2Storage::Planned::AssignedSpace.new(space, []) }
+    let(:space) do
+      instance_double(
+        "Y2Storage::FreeDiskSpace",
+        disk:                   disk,
+        disk_size:              500.GiB,
+        align_grain:            1.MiB,
+        require_end_alignment?: false
+      )
+    end
+
+    let(:disk) { instance_double("Y2Storage::Disk", devicegraph: devicegraph) }
+    let(:devicegraph) { instance_double("Y2Storage::Devicegraph") }
+
+    context "when the plan is to create a new partition" do
+      it "returns false" do
+        expect(partition.subsequent_slot?(assigned_space)).to eq false
+      end
+    end
+
+    context "when the plan is to reuse an existing partition" do
+      let(:real_partition) { instance_double("Y2Storage::Partition", sid: 123) 
}
+
+      before do
+        partition.assign_reuse(real_partition)
+
+        allow(devicegraph).to receive(:find_device).and_return real_partition
+        allow(real_partition).to 
receive(:subsequent_slot?).with(space).and_return subsequent
+      end
+
+      context "if the reused partition is next to the region of the assigned 
space" do
+        let(:subsequent) { true }
+
+        it "returns true" do
+          expect(partition.subsequent_slot?(assigned_space)).to eq true
+        end
+      end
+
+      context "if the reused partition is not adjacent to the region of the 
assigned space" do
+        let(:subsequent) { false }
+
+        it "returns false" do
+          expect(partition.subsequent_slot?(assigned_space)).to eq false
+        end
+      end
+    end
+  end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/test/y2storage/proposal/space_maker_bigger_resize_test.rb
 
new/yast2-storage-ng-5.0.18/test/y2storage/proposal/space_maker_bigger_resize_test.rb
--- 
old/yast2-storage-ng-5.0.17/test/y2storage/proposal/space_maker_bigger_resize_test.rb
       2024-08-26 17:03:52.000000000 +0200
+++ 
new/yast2-storage-ng-5.0.18/test/y2storage/proposal/space_maker_bigger_resize_test.rb
       2024-09-20 15:57:19.000000000 +0200
@@ -39,8 +39,10 @@
     settings.space_settings.actions = settings_actions
     settings
   end
-  let(:settings_actions) { {} }
+  let(:settings_actions) { [] }
   let(:analyzer) { Y2Storage::DiskAnalyzer.new(fake_devicegraph) }
+  let(:delete) { Y2Storage::SpaceActions::Delete }
+  let(:resize) { Y2Storage::SpaceActions::Resize }
 
   subject(:maker) { described_class.new(analyzer, settings) }
 
@@ -48,7 +50,7 @@
     let(:scenario) { "complex-lvm-encrypt" }
 
     context "if no device is set as :force_delete " do
-      let(:settings_actions) { { "/dev/sda1" => :delete, "/dev/sda2" => 
:delete } }
+      let(:settings_actions) { [delete.new("/dev/sda1"), 
delete.new("/dev/sda2")] }
 
       it "does not delete any partition" do
         result = maker.prepare_devicegraph(fake_devicegraph)
@@ -56,9 +58,9 @@
       end
     end
 
-    # :force_delete for disks should be ignored, actions only make sense for 
partitions and LVs
+    # Mandatory delete for disks should be ignored, actions only make sense 
for partitions and LVs
     context "if :force_delete is specified for a disk that contains 
partitions" do
-      let(:settings_actions) { { "/dev/sda" => :force_delete } }
+      let(:settings_actions) { [delete.new("/dev/sda", mandatory: true)] }
 
       it "does not delete any partition" do
         result = maker.prepare_devicegraph(fake_devicegraph)
@@ -68,6 +70,9 @@
 
     context "if :force_delete is specified for several partitions" do
       let(:settings_actions) { { "/dev/sda2" => :force_delete, "/dev/sde1" => 
:force_delete } }
+      let(:settings_actions) do
+        [delete.new("/dev/sda2", mandatory: true), delete.new("/dev/sde1", 
mandatory: true)]
+      end
 
       it "does not delete partitions out of SpaceMaker#candidate_devices" do
         result = maker.prepare_devicegraph(fake_devicegraph)
@@ -80,11 +85,14 @@
       end
     end
 
-    # :force_delete for disks should be ignored, actions only make sense for 
partitions and LVs
+    # Mandatory delete for disks should be ignored, actions only make sense 
for partitions and LVs
     context "if :force_delete is specified for a directly formatted disk (no 
partition table)" do
       let(:scenario) { "multipath-formatted.xml" }
 
-      let(:settings_actions) { { "/dev/mapper/0QEMU_QEMU_HARDDISK_mpath1" => 
:force_delete } }
+      let(:settings_actions) do
+        [delete.new("/dev/mapper/0QEMU_QEMU_HARDDISK_mpath1", mandatory: true)]
+      end
+
       before do
         settings.candidate_devices = ["/dev/mapper/0QEMU_QEMU_HARDDISK_mpath1"]
         settings.root_device = "/dev/mapper/0QEMU_QEMU_HARDDISK_mpath1"
@@ -104,7 +112,7 @@
 
     context "when deleting a btrfs partition that is part of a multidevice 
btrfs" do
       let(:scenario) { "btrfs-multidevice-over-partitions.xml" }
-      let(:settings_actions) { { "/dev/sda1" => :force_delete } }
+      let(:settings_actions) { [delete.new("/dev/sda1", mandatory: true)] }
 
       it "deletes the partitions explicitly mentioned in the settings" do
         result = maker.prepare_devicegraph(fake_devicegraph)
@@ -119,7 +127,7 @@
 
     context "when deleting a partition that is part of a raid" do
       let(:scenario) { "raid0-over-partitions.xml" }
-      let(:settings_actions) { { "/dev/sda1" => :force_delete } }
+      let(:settings_actions) { [delete.new("/dev/sda1", mandatory: true)] }
 
       it "deletes the partitions explicitly mentioned in the settings" do
         result = maker.prepare_devicegraph(fake_devicegraph)
@@ -134,7 +142,7 @@
 
     context "when deleting a partition that is part of a lvm volume group" do
       let(:scenario) { "lvm-over-partitions.xml" }
-      let(:settings_actions) { { "/dev/sda1" => :force_delete } }
+      let(:settings_actions) { [delete.new("/dev/sda1", mandatory: true)] }
 
       it "deletes the partitions explicitly mentioned in the settings" do
         result = maker.prepare_devicegraph(fake_devicegraph)
@@ -146,6 +154,31 @@
         expect(result.partitions.map(&:name)).to include "/dev/sda2", 
"/dev/sda3", "/dev/sdb2"
       end
     end
+
+    context "if there is a resize action with a max that is smaller than the 
partition size" do
+      using Y2Storage::Refinements::SizeCasts
+
+      let(:scenario) { "irst-windows-linux-gpt" }
+      let(:settings_actions) do
+        [resize.new("/dev/sda2"), resize.new("/dev/sda3", max_size: 200.GiB)]
+      end
+
+      let(:resize_info) do
+        instance_double("ResizeInfo", resize_ok?: true, min_size: 100.GiB, 
max_size: 800.GiB)
+      end
+
+      before do
+        allow_any_instance_of(Y2Storage::Partition)
+          .to receive(:detect_resize_info).and_return(resize_info)
+      end
+
+      it "resizes the partition to the specified max if possible" do
+        result = maker.prepare_devicegraph(fake_devicegraph)
+        expect(result.partitions).to include(
+          an_object_having_attributes(filesystem_label: "other", size: 200.GiB)
+        )
+      end
+    end
   end
 
   describe "#provide_space" do
@@ -254,10 +287,10 @@
 
       context "if resizing some partitions and deleting others is allowed" do
         let(:settings_actions) do
-          {
-            "/dev/sda2" => :resize, "/dev/sda3" => :resize,
-            "/dev/sda5" => :delete, "/dev/sda6" => :delete
-          }
+          [
+            resize.new("/dev/sda2"), resize.new("/dev/sda3"),
+            delete.new("/dev/sda5"), delete.new("/dev/sda6")
+          ]
         end
 
         context "and resizing one partition is enough" do
@@ -285,7 +318,7 @@
           end
         end
 
-        context "and resizing one partition is not enough" do
+        context "and resizing one partition is not enough because more space 
is needed" do
           let(:volumes) { [vol1, vol2] }
 
           it "resizes subsequent partitions" do
@@ -311,6 +344,39 @@
           end
         end
 
+        context "and resizing one partition is not enough because the action 
is limited" do
+          let(:volumes) { [vol1] }
+
+          let(:settings_actions) do
+            [
+              resize.new("/dev/sda2", min_size: 250.GiB), 
resize.new("/dev/sda3"),
+              delete.new("/dev/sda5"), delete.new("/dev/sda6")
+            ]
+          end
+
+          it "resizes the more 'productive' partition taking restrictions into 
account" do
+            result = maker.provide_space(fake_devicegraph, volumes, lvm_helper)
+            expect(result[:devicegraph].partitions).to include(
+              an_object_having_attributes(filesystem_label: "windows", size: 
360.GiB),
+              an_object_having_attributes(filesystem_label: "other", size: 
110.GiB)
+            )
+          end
+
+          it "does not delete any partition" do
+            result = maker.provide_space(fake_devicegraph, volumes, lvm_helper)
+            expect(result[:devicegraph].partitions.map(&:name)).to 
contain_exactly(
+              "/dev/sda1", "/dev/sda2", "/dev/sda3", "/dev/sda4", "/dev/sda5"
+            )
+          end
+
+          it "suggests a distribution using the freed space" do
+            result = maker.provide_space(fake_devicegraph, volumes, lvm_helper)
+            distribution = result[:partitions_distribution]
+            expect(distribution.spaces.size).to eq 1
+            expect(distribution.spaces.first.partitions).to eq volumes
+          end
+        end
+
         context "and resizing all the allowed partitions is not enough" do
           let(:volumes) { [vol1, vol2, vol3] }
 
@@ -335,6 +401,24 @@
             expect(distribution.spaces.size).to eq 3
             expect(distribution.spaces.flat_map(&:partitions)).to 
contain_exactly(*volumes)
           end
+
+          context "if resize operations are limited" do
+            let(:settings_actions) do
+              [
+                resize.new("/dev/sda2", min_size: 150.GiB),
+                resize.new("/dev/sda3", min_size: 110.GiB),
+                delete.new("/dev/sda5"), delete.new("/dev/sda6")
+              ]
+            end
+
+            it "resizes all allowed partitions their specified limits" do
+              result = maker.provide_space(fake_devicegraph, volumes, 
lvm_helper)
+              expect(result[:devicegraph].partitions).to include(
+                an_object_having_attributes(filesystem_label: "windows", size: 
150.GiB),
+                an_object_having_attributes(filesystem_label: "other", size: 
110.GiB)
+              )
+            end
+          end
         end
       end
     end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/test/y2storage/proposal_agama_advanced_test.rb 
new/yast2-storage-ng-5.0.18/test/y2storage/proposal_agama_advanced_test.rb
--- old/yast2-storage-ng-5.0.17/test/y2storage/proposal_agama_advanced_test.rb  
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/test/y2storage/proposal_agama_advanced_test.rb  
2024-09-20 15:57:19.000000000 +0200
@@ -42,6 +42,9 @@
       { "mount_point" => "swap", "fs_type" => "swap", "min_size" => "1 GiB", 
"max_size" => "2 GiB" }
     end
 
+    let(:delete) { Y2Storage::SpaceActions::Delete }
+    let(:resize) { Y2Storage::SpaceActions::Resize }
+
     let(:scenario) { "mixed_disks" }
 
     before do
@@ -70,7 +73,7 @@
       before do
         settings.candidate_devices = ["/dev/sdb"]
         settings.root_device = "/dev/sda"
-        settings.space_settings.actions = { "/dev/sda1" => :resize, 
"/dev/sda2" => :resize }
+        settings.space_settings.actions = [resize.new("/dev/sda1"), 
resize.new("/dev/sda2")]
         allow(storage_arch).to receive(:efiboot?).and_return(true)
       end
 
@@ -127,7 +130,7 @@
         it "tries to use the formatted disk before trying an optional delete" 
do
           sda1_sid = fake_devicegraph.find_by_name("/dev/sda1").sid
 
-          settings.space_settings.actions = { "/dev/sda1" => :delete }
+          settings.space_settings.actions = [delete.new("/dev/sda1")]
           proposal.propose
           expect(proposal.failed?).to eq false
 
@@ -141,7 +144,7 @@
         it "tries to use the formatted disk before trying an optional resize" 
do
           orig_sda1 = fake_devicegraph.find_by_name("/dev/sda1")
 
-          settings.space_settings.actions = { "/dev/sda1" => :resize }
+          settings.space_settings.actions = [resize.new("/dev/sda1")]
           proposal.propose
           expect(proposal.failed?).to eq false
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/test/y2storage/proposal_agama_basis_test.rb 
new/yast2-storage-ng-5.0.18/test/y2storage/proposal_agama_basis_test.rb
--- old/yast2-storage-ng-5.0.17/test/y2storage/proposal_agama_basis_test.rb     
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/test/y2storage/proposal_agama_basis_test.rb     
2024-09-20 15:57:19.000000000 +0200
@@ -252,11 +252,11 @@
 
       before do
         settings.space_settings.strategy = :bigger_resize
-        settings.space_settings.actions = {
-          "/dev/sda1" => :resize,
-          "/dev/sdb1" => :resize,
-          "/dev/sdc1" => :resize
-        }
+        settings.space_settings.actions = [
+          Y2Storage::SpaceActions::Resize.new("/dev/sda1"),
+          Y2Storage::SpaceActions::Resize.new("/dev/sdb1"),
+          Y2Storage::SpaceActions::Resize.new("/dev/sdc1")
+        ]
       end
 
       include_examples "resize volume combinations"
@@ -275,11 +275,11 @@
 
       before do
         settings.space_settings.strategy = :bigger_resize
-        settings.space_settings.actions = {
-          "/dev/sda1" => :force_delete,
-          "/dev/sdb1" => :force_delete,
-          "/dev/sdc1" => :force_delete
-        }
+        settings.space_settings.actions = [
+          Y2Storage::SpaceActions::Delete.new("/dev/sda1", mandatory: true),
+          Y2Storage::SpaceActions::Delete.new("/dev/sdb1", mandatory: true),
+          Y2Storage::SpaceActions::Delete.new("/dev/sdc1", mandatory: true)
+        ]
       end
 
       include_examples "delete volume combinations"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-5.0.17/test/y2storage/proposal_agama_reuse_test.rb 
new/yast2-storage-ng-5.0.18/test/y2storage/proposal_agama_reuse_test.rb
--- old/yast2-storage-ng-5.0.17/test/y2storage/proposal_agama_reuse_test.rb     
2024-08-26 17:03:52.000000000 +0200
+++ new/yast2-storage-ng-5.0.18/test/y2storage/proposal_agama_reuse_test.rb     
2024-09-20 15:57:19.000000000 +0200
@@ -34,7 +34,7 @@
     let(:settings_format) { :ng }
     let(:separate_home) { true }
     let(:control_file_content) { { "partitioning" => { "volumes" => volumes } 
} }
-    let(:space_actions) { {} }
+    let(:space_actions) { [] }
 
     let(:scenario) { "lvm-two-vgs" }
     let(:resize_info) do
@@ -57,6 +57,9 @@
       { "mount_point" => "swap", "fs_type" => "swap", "min_size" => "2 GiB", 
"max_size" => "6 GiB" }
     end
 
+    let(:delete) { Y2Storage::SpaceActions::Delete }
+    let(:resize) { Y2Storage::SpaceActions::Resize }
+
     before do
       # Speed-up things by avoiding calls to hwinfo
       allow_any_instance_of(Y2Storage::Disk).to 
receive(:hwinfo).and_return(Y2Storage::HWInfoDisk.new)
@@ -82,7 +85,9 @@
         srv.reformat = reformat
       end
 
-      let(:space_actions) { { "/dev/sda1" => :delete, "/dev/sda2" => :delete, 
"/dev/sda8" => :delete } }
+      let(:space_actions) do
+        [delete.new("/dev/sda1"), delete.new("/dev/sda2"), 
delete.new("/dev/sda8")]
+      end
       let(:original_sda8) { fake_devicegraph.find_by_name("/dev/sda8") }
 
       context "keeping its filesystem" do
@@ -129,7 +134,7 @@
         srv.reformat = reformat
       end
 
-      let(:space_actions) { { "/dev/sda1" => :delete, "/dev/sda4" => :delete } 
}
+      let(:space_actions) { [delete.new("/dev/sda1"), delete.new("/dev/sda4")] 
}
       let(:original_sda4) { fake_devicegraph.find_by_name("/dev/sda4") }
 
       context "keeping its filesystem" do
@@ -178,7 +183,9 @@
         srv.reformat = reformat
       end
 
-      let(:space_actions) { { "/dev/sda1" => :delete, "/dev/sda2" => :delete, 
"/dev/sda5" => :delete } }
+      let(:space_actions) do
+        [delete.new("/dev/sda1"), delete.new("/dev/sda2"), 
delete.new("/dev/sda5")]
+      end
       let(:original_sda5) { fake_devicegraph.find_by_name("/dev/sda5") }
 
       context "keeping its filesystem" do
@@ -316,7 +323,7 @@
           srv.reuse_name = "/dev/md1"
         end
 
-        let(:space_actions) { { "/dev/sda2" => :delete, "/dev/sdb2" => :delete 
} }
+        let(:space_actions) { [delete.new("/dev/sda2"), 
delete.new("/dev/sdb2")] }
 
         let(:original_sda2) { fake_devicegraph.find_by_name("/dev/sda2") }
         let(:original_sdb2) { fake_devicegraph.find_by_name("/dev/sdb2") }
@@ -345,7 +352,7 @@
           srv.reuse_name = "/dev/md0"
         end
 
-        let(:space_actions) { { "/dev/sda1" => :delete, "/dev/sdb1" => :delete 
} }
+        let(:space_actions) { [delete.new("/dev/sda1"), 
delete.new("/dev/sdb1")] }
 
         let(:original_sda1) { fake_devicegraph.find_by_name("/dev/sda1") }
         let(:original_sdb1) { fake_devicegraph.find_by_name("/dev/sdb1") }
@@ -383,7 +390,7 @@
         srv.reformat = false
       end
 
-      let(:space_actions) { { "/dev/sda2" => :delete, "/dev/sdb2" => :delete } 
}
+      let(:space_actions) { [delete.new("/dev/sda2"), delete.new("/dev/sdb2")] 
}
 
       let(:original_sda2) { fake_devicegraph.find_by_name("/dev/sda2") }
       let(:original_sdb2) { fake_devicegraph.find_by_name("/dev/sdb2") }
@@ -413,7 +420,7 @@
         srv.reformat = false
       end
 
-      let(:space_actions) { { "/dev/sda2" => :delete, "/dev/sdb2" => :delete } 
}
+      let(:space_actions) { [delete.new("/dev/sda2"), delete.new("/dev/sdb2")] 
}
 
       let(:original_sda2) { fake_devicegraph.find_by_name("/dev/sda2") }
       let(:original_sdb2) { fake_devicegraph.find_by_name("/dev/sdb2") }
@@ -477,10 +484,10 @@
       end
 
       let(:space_actions) do
-        {
-          "/dev/sda1" => :delete, "/dev/sda2" => :delete, "/dev/sda3" => 
:delete,
-          "/dev/sdb1" => :delete, "/dev/sdb2" => :delete
-        }
+        [
+          delete.new("/dev/sda1"), delete.new("/dev/sda2"), 
delete.new("/dev/sda3"),
+          delete.new("/dev/sdb1"), delete.new("/dev/sdb2")
+        ]
       end
 
       let(:original_sdb1) { fake_devicegraph.find_by_name("/dev/sdb1") }

Reply via email to