Hello community,

here is the log from the commit of package yast2-storage-ng for 
openSUSE:Factory checked in at 2018-02-07 18:37:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yast2-storage-ng (Old)
 and      /work/SRC/openSUSE:Factory/.yast2-storage-ng.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yast2-storage-ng"

Wed Feb  7 18:37:34 2018 rev:5 rq:573829 version:4.0.84

Changes:
--------
--- /work/SRC/openSUSE:Factory/yast2-storage-ng/yast2-storage-ng.changes        
2018-02-02 22:18:41.883915107 +0100
+++ /work/SRC/openSUSE:Factory/.yast2-storage-ng.new/yast2-storage-ng.changes   
2018-02-07 18:37:34.786957456 +0100
@@ -1,0 +2,12 @@
+Wed Feb  7 00:18:34 UTC 2018 - [email protected]
+
+- Partitioner: fixed 'Device Graph' section (part of fate#318196).
+- 4.0.84
+
+-------------------------------------------------------------------
+Mon Feb  5 15:26:35 UTC 2018 - [email protected]
+
+- Added a new 'disk' client, alias for 'partitioner' (bsc#1078900).
+- 4.0.83
+
+-------------------------------------------------------------------

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

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

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

Other differences:
------------------
++++++ yast2-storage-ng.spec ++++++
--- /var/tmp/diff_new_pack.EHnQ7r/_old  2018-02-07 18:37:35.250935720 +0100
+++ /var/tmp/diff_new_pack.EHnQ7r/_new  2018-02-07 18:37:35.254935532 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-storage-ng
-Version:        4.0.82
+Version:        4.0.84
 Release:        0
 BuildArch:      noarch
 

++++++ yast2-storage-ng-4.0.82.tar.bz2 -> yast2-storage-ng-4.0.84.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-4.0.82/package/yast2-storage-ng.changes 
new/yast2-storage-ng-4.0.84/package/yast2-storage-ng.changes
--- old/yast2-storage-ng-4.0.82/package/yast2-storage-ng.changes        
2018-02-01 11:13:40.000000000 +0100
+++ new/yast2-storage-ng-4.0.84/package/yast2-storage-ng.changes        
2018-02-07 10:51:09.000000000 +0100
@@ -1,4 +1,16 @@
 -------------------------------------------------------------------
+Wed Feb  7 00:18:34 UTC 2018 - [email protected]
+
+- Partitioner: fixed 'Device Graph' section (part of fate#318196).
+- 4.0.84
+
+-------------------------------------------------------------------
+Mon Feb  5 15:26:35 UTC 2018 - [email protected]
+
+- Added a new 'disk' client, alias for 'partitioner' (bsc#1078900).
+- 4.0.83
+
+-------------------------------------------------------------------
 Wed Jan 31 16:06:25 UTC 2018 - [email protected]
 
 - Handle arbitrary mount options for /etc/fstab properly
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-4.0.82/package/yast2-storage-ng.spec 
new/yast2-storage-ng-4.0.84/package/yast2-storage-ng.spec
--- old/yast2-storage-ng-4.0.82/package/yast2-storage-ng.spec   2018-02-01 
11:13:40.000000000 +0100
+++ new/yast2-storage-ng-4.0.84/package/yast2-storage-ng.spec   2018-02-07 
10:51:09.000000000 +0100
@@ -16,7 +16,7 @@
 #
 
 Name:          yast2-storage-ng
-Version:        4.0.82
+Version:        4.0.84
 Release:       0
 BuildArch:     noarch
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-storage-ng-4.0.82/src/clients/disk.rb 
new/yast2-storage-ng-4.0.84/src/clients/disk.rb
--- old/yast2-storage-ng-4.0.82/src/clients/disk.rb     1970-01-01 
01:00:00.000000000 +0100
+++ new/yast2-storage-ng-4.0.84/src/clients/disk.rb     2018-02-07 
18:37:35.578920354 +0100
@@ -0,0 +1 @@
+symbolic link to partitioner.rb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-storage-ng-4.0.82/src/clients/storage.rb 
new/yast2-storage-ng-4.0.84/src/clients/storage.rb
--- old/yast2-storage-ng-4.0.82/src/clients/storage.rb  1970-01-01 
01:00:00.000000000 +0100
+++ new/yast2-storage-ng-4.0.84/src/clients/storage.rb  2018-02-07 
18:37:35.586919979 +0100
@@ -0,0 +1 @@
+symbolic link to partitioner.rb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-4.0.82/src/lib/y2partitioner/widgets/device_graph_with_buttons.rb
 
new/yast2-storage-ng-4.0.84/src/lib/y2partitioner/widgets/device_graph_with_buttons.rb
--- 
old/yast2-storage-ng-4.0.82/src/lib/y2partitioner/widgets/device_graph_with_buttons.rb
      1970-01-01 01:00:00.000000000 +0100
+++ 
new/yast2-storage-ng-4.0.84/src/lib/y2partitioner/widgets/device_graph_with_buttons.rb
      2018-02-07 10:51:09.000000000 +0100
@@ -0,0 +1,136 @@
+# encoding: utf-8
+
+# Copyright (c) [2018] 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 "yast"
+require "cwm"
+require "y2partitioner/widgets/visual_device_graph"
+
+Yast.import "UI"
+
+module Y2Partitioner
+  module Widgets
+    # Widget to display a devicegraph and the corresponding buttons to export 
it
+    #
+    # It works only in graphical UI (i.e. the Graph widget is available) don't
+    # use it in NCurses.
+    class DeviceGraphWithButtons < CWM::CustomWidget
+      # Constructor
+      def initialize(device_graph, pager)
+        textdomain "storage"
+
+        @device_graph = device_graph
+        @pager = pager
+      end
+
+      # @macro seeCustomWidget
+      def contents
+        VBox(
+          VisualDeviceGraph.new(device_graph, pager),
+          Left(
+            HBox(
+              SaveDeviceGraphButton.new(device_graph, :xml),
+              SaveDeviceGraphButton.new(device_graph, :gv)
+            )
+          )
+        )
+      end
+
+    private
+
+      # @return [Devicegraph] graph to display
+      attr_reader :device_graph
+
+      # @return [CWM::TreePager] main pager used to jump to the different
+      #   partitioner sections
+      attr_reader :pager
+    end
+
+    # Widget for exporting a devicegraph in XML or Grapviz format
+    class SaveDeviceGraphButton < CWM::PushButton
+      # Configuration of the Graphviz export (information in the vertices)
+      LABEL_FLAGS = Storage::GraphvizFlags_DISPLAYNAME
+
+      # Configuration of the Graphviz export (tooltips)
+      TOOLTIP_FLAGS = Storage::GraphvizFlags_PRETTY_CLASSNAME |
+        Storage::GraphvizFlags_SIZE | Storage::GraphvizFlags_SID |
+        Storage::GraphvizFlags_ACTIVE | Storage::GraphvizFlags_IN_ETC
+
+      private_constant :LABEL_FLAGS, :TOOLTIP_FLAGS
+
+      # Constructor
+      def initialize(device_graph, format)
+        textdomain "storage"
+
+        @device_graph = device_graph
+        @format = format
+        @widget_id = "#{widget_id}_#{device_graph.object_id}_#{format}"
+      end
+
+      # @macro seeAbstractWidget
+      def label
+        if xml?
+          _("Save as XML...")
+        else
+          _("Save as Graphviz...")
+        end
+      end
+
+      # @macro seeAbstractWidget
+      def handle
+        filename = Yast::UI.AskForSaveFileName("/tmp/yast.#{format}", 
"*.#{format}", "Save as...")
+        return if filename.nil?
+        return if save(filename)
+
+        # TRANSLATORS: Error pop-up message
+        Yast::Popup.Error(_("Saving graph file failed."))
+      end
+
+    private
+
+      # @return [Devicegraph] graph to display and export
+      attr_reader :device_graph
+
+      # @return [Symbol] :xml or :gv
+      attr_reader :format
+
+      # Whether this button exports to XML
+      def xml?
+        format == :xml
+      end
+
+      # Saves the device graph into the corresponding XML or Graphviz file
+      #
+      # @param filename [String]
+      # @return [Boolean] true if the file was successfully written, false
+      #   otherwise
+      def save(filename)
+        if xml?
+          device_graph.save(filename)
+        else
+          device_graph.write_graphviz(filename, LABEL_FLAGS, TOOLTIP_FLAGS)
+        end
+        true
+      rescue Storage::Exception
+        false
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-4.0.82/src/lib/y2partitioner/widgets/overview.rb 
new/yast2-storage-ng-4.0.84/src/lib/y2partitioner/widgets/overview.rb
--- old/yast2-storage-ng-4.0.82/src/lib/y2partitioner/widgets/overview.rb       
2018-02-01 11:13:40.000000000 +0100
+++ new/yast2-storage-ng-4.0.84/src/lib/y2partitioner/widgets/overview.rb       
2018-02-07 10:51:09.000000000 +0100
@@ -30,6 +30,8 @@
 require "y2partitioner/setup_errors_presenter"
 require "y2storage/setup_checker"
 
+Yast.import "UI"
+
 module Y2Partitioner
   module Widgets
     # A dummy page for prototyping
@@ -89,10 +91,7 @@
       def items
         [
           system_items,
-          # TODO: only if there is graph support UI.HasSpecialWidget(:Graph)
-          item_for("devicegraph", _("Device Graph"), icon: Icons::GRAPH),
-          # TODO: only if there is graph support UI.HasSpecialWidget(:Graph)
-          item_for("mountgraph", _("Mount Graph"), icon: Icons::GRAPH),
+          *graph_items,
           item_for("summary", _("Installation Summary"), icon: Icons::SUMMARY),
           item_for("settings", _("Settings"), icon: Icons::SETTINGS)
         ]
@@ -146,12 +145,14 @@
 
     private
 
+      # @return [String]
       attr_reader :hostname
 
       def device_graph
         DeviceGraphs.instance.current
       end
 
+      # @return [CWM::PagerTreeItem]
       def system_items
         page = Pages::System.new(hostname, self)
         children = [
@@ -167,6 +168,7 @@
         CWM::PagerTreeItem.new(page, children: children, icon: Icons::ALL)
       end
 
+      # @return [CWM::PagerTreeItem]
       def disks_items
         devices = device_graph.disk_devices
         page = Pages::Disks.new(devices, self)
@@ -174,17 +176,20 @@
         CWM::PagerTreeItem.new(page, children: children, icon: Icons::HD)
       end
 
+      # @return [CWM::PagerTreeItem]
       def disk_items(disk)
         page = Pages::Disk.new(disk, self)
         children = disk.partitions.sort_by(&:number).map { |p| 
partition_items(p) }
         CWM::PagerTreeItem.new(page, children: children)
       end
 
+      # @return [CWM::PagerTreeItem]
       def partition_items(partition)
         page = Pages::Partition.new(partition)
         CWM::PagerTreeItem.new(page)
       end
 
+      # @return [CWM::PagerTreeItem]
       def raids_items
         devices = device_graph.software_raids
         page = Pages::MdRaids.new(self)
@@ -192,11 +197,13 @@
         CWM::PagerTreeItem.new(page, children: children, icon: Icons::RAID)
       end
 
+      # @return [CWM::PagerTreeItem]
       def raid_items(md)
         page = Pages::MdRaid.new(md, self)
         CWM::PagerTreeItem.new(page)
       end
 
+      # @return [CWM::PagerTreeItem]
       def lvm_items
         devices = device_graph.lvm_vgs
         page = Pages::Lvm.new(self)
@@ -204,41 +211,60 @@
         CWM::PagerTreeItem.new(page, children: children, icon: Icons::LVM)
       end
 
+      # @return [CWM::PagerTreeItem]
       def lvm_vg_items(vg)
         page = Pages::LvmVg.new(vg, self)
         children = vg.all_lvm_lvs.sort_by(&:lv_name).map { |l| lvm_lv_items(l) 
}
         CWM::PagerTreeItem.new(page, children: children)
       end
 
+      # @return [CWM::PagerTreeItem]
       def lvm_lv_items(lv)
         page = Pages::LvmLv.new(lv)
         CWM::PagerTreeItem.new(page)
       end
 
+      # @return [CWM::PagerTreeItem]
       def crypt_files_items
         # TODO: real subtree
         item_for("loop", _("Crypt Files"), icon: Icons::LOOP, subtree: [])
       end
 
+      # @return [CWM::PagerTreeItem]
       def device_mapper_items
         # TODO: real subtree
         item_for("dm", _("Device Mapper"), icon: Icons::DM, subtree: [])
       end
 
+      # @return [CWM::PagerTreeItem]
       def nfs_items
         page = Pages::NfsMounts.new(self)
         CWM::PagerTreeItem.new(page, icon: Icons::NFS)
       end
 
+      # @return [CWM::PagerTreeItem]
       def btrfs_items
         page = Pages::Btrfs.new(self)
         CWM::PagerTreeItem.new(page, icon: Icons::BTRFS)
       end
 
+      # @return [CWM::PagerTreeItem]
       def unused_items
         item_for("unused", _("Unused Devices"), icon: Icons::UNUSED)
       end
 
+      # @return [Array<CWM::PagerTreeItem>]
+      def graph_items
+        return [] unless Yast::UI.HasSpecialWidget(:Graph)
+
+        page = Pages::DeviceGraph.new(self)
+        dev_item = CWM::PagerTreeItem.new(page, icon: Icons::GRAPH)
+        mount_item = item_for("mountgraph", _("Mount Graph"), icon: 
Icons::GRAPH)
+
+        [dev_item, mount_item]
+      end
+
+      # @return [CWM::PagerTreeItem]
       def item_for(id, label, widget: nil, icon: nil, subtree: [])
         text = id.to_s.split(":", 2)[1] || id.to_s
         widget ||= Heading(text)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-4.0.82/src/lib/y2partitioner/widgets/pages/device_graph.rb 
new/yast2-storage-ng-4.0.84/src/lib/y2partitioner/widgets/pages/device_graph.rb
--- 
old/yast2-storage-ng-4.0.82/src/lib/y2partitioner/widgets/pages/device_graph.rb 
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/yast2-storage-ng-4.0.84/src/lib/y2partitioner/widgets/pages/device_graph.rb 
    2018-02-07 10:51:09.000000000 +0100
@@ -0,0 +1,146 @@
+# encoding: utf-8
+
+# Copyright (c) [2018] 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 "y2partitioner/icons"
+require "y2partitioner/device_graphs"
+require "y2partitioner/widgets/device_graph_with_buttons"
+
+module Y2Partitioner
+  module Widgets
+    module Pages
+      # A page for displaying the device graphs (both current and system) in
+      # interfaces supporting the Graph widget (Qt). Don't use in NCurses.
+      class DeviceGraph < CWM::Page
+        include Yast::I18n
+
+        # Constructor
+        #
+        # @param pager [CWM::TreePager]
+        def initialize(pager)
+          textdomain "storage"
+
+          @pager = pager
+        end
+
+        # @macro seeAbstractWidget
+        def label
+          _("Device Graph")
+        end
+
+        # @macro seeCustomWidget
+        def contents
+          return @contents if @contents
+
+          icon = Icons.small_icon(Icons::GRAPH)
+          @tabs = Tabs.new(current_tab, system_tab)
+          @contents = VBox(
+            Left(
+              HBox(
+                Image(icon, ""),
+                # TRANSLATORS: Heading for the expert partitioner page
+                Heading(_("Device Graphs"))
+              )
+            ),
+            @tabs
+          )
+        end
+
+        # @macro seeAbstractWidget
+        def init
+          # Start always in the first tab
+          @tabs.switch_page(@tabs.initial_page)
+        end
+
+      private
+
+        # @return [CWM::TreePager]
+        attr_reader :pager
+
+        # Tab displaying the current devicegraph with a brief explanation
+        def current_tab
+          DeviceGraphTab.new(
+            # TRANSLATORS: label for a tab
+            _("Planned Devices"),
+            DeviceGraphs.instance.current,
+            # TRANSLATORS: keep lines relatively short. Use \n if needed
+            _(
+              "Final result that will be committed to the system.\n" \
+              "This graph is updated on every user action."
+            ),
+            pager
+          )
+        end
+
+        # Tab displaying the system devicegraph with a brief explanation
+        def system_tab
+          DeviceGraphTab.new(
+            # TRANSLATORS: label for a tab
+            _("Current System Devices"),
+            DeviceGraphs.instance.system,
+            # TRANSLATORS: keep lines relatively short. Use \n if needed
+            _(
+              "Layout of the current system, before any of the scheduled 
changes.\n" \
+              "This graph is created at startup. Updated if devices are 
rescanned."
+            ),
+            pager
+          )
+        end
+      end
+
+      # Class to represent every tab in the Device Graph page
+      class DeviceGraphTab < CWM::Tab
+        # @return [String]
+        attr_reader :label
+
+        # Constructor
+        def initialize(label, device_graph, description, pager)
+          @label = label
+          @device_graph = device_graph
+          @widget_id = "#{widget_id}_#{device_graph.object_id}"
+          @description = description
+          @pager = pager
+        end
+
+        # @macro seeCustomWidget
+        def contents
+          return @contents if @contents
+
+          @contents = VBox(
+            Left(Label(description)),
+            DeviceGraphWithButtons.new(device_graph, pager)
+          )
+        end
+
+      private
+
+        # @return [String] explanation to display above the graph
+        attr_reader :description
+
+        # @return [Devicegraph] graph to display
+        attr_reader :device_graph
+
+        # @return [CWM::TreePager] main pager used to jump to the different
+        #   partitioner sections
+        attr_reader :pager
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-4.0.82/src/lib/y2partitioner/widgets/pages.rb 
new/yast2-storage-ng-4.0.84/src/lib/y2partitioner/widgets/pages.rb
--- old/yast2-storage-ng-4.0.82/src/lib/y2partitioner/widgets/pages.rb  
2018-02-01 11:13:40.000000000 +0100
+++ new/yast2-storage-ng-4.0.84/src/lib/y2partitioner/widgets/pages.rb  
2018-02-07 10:51:09.000000000 +0100
@@ -39,3 +39,4 @@
 require "y2partitioner/widgets/pages/lvm_vg.rb"
 require "y2partitioner/widgets/pages/partition.rb"
 require "y2partitioner/widgets/pages/nfs_mounts.rb"
+require "y2partitioner/widgets/pages/device_graph.rb"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-4.0.82/src/lib/y2partitioner/widgets/visual_device_graph.rb
 
new/yast2-storage-ng-4.0.84/src/lib/y2partitioner/widgets/visual_device_graph.rb
--- 
old/yast2-storage-ng-4.0.82/src/lib/y2partitioner/widgets/visual_device_graph.rb
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/yast2-storage-ng-4.0.84/src/lib/y2partitioner/widgets/visual_device_graph.rb
    2018-02-07 10:51:09.000000000 +0100
@@ -0,0 +1,132 @@
+# encoding: utf-8
+
+# Copyright (c) [2018] 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 "yast"
+require "cwm"
+require "y2storage"
+require "tempfile"
+
+module Y2Partitioner
+  module Widgets
+    # Widget to display a devicegraph
+    #
+    # It works only in graphical UI (i.e. the Graph widget is available) don't
+    # use it in NCurses.
+    class VisualDeviceGraph < CWM::CustomWidget
+      # Configuration of the Graphviz export (information in the vertices)
+      LABEL_FLAGS = Storage::GraphvizFlags_DISPLAYNAME
+
+      # Configuration of the Graphviz export (tooltips)
+      TOOLTIP_FLAGS = Storage::GraphvizFlags_PRETTY_CLASSNAME |
+        Storage::GraphvizFlags_SIZE | Storage::GraphvizFlags_NAME
+
+      private_constant :LABEL_FLAGS, :TOOLTIP_FLAGS
+
+      # Constructor
+      def initialize(device_graph, pager)
+        textdomain "storage"
+
+        @device_graph = device_graph
+        @pager = pager
+        @widget_id = "#{widget_id}_#{device_graph.object_id}"
+      end
+
+      # @macro seeCustomWidget
+      def contents
+        ReplacePoint(replace_point_id, Empty(graph_id))
+      end
+
+      # @macro seeAbstractWidget
+      def init
+        tmp = Tempfile.new("graph.gv")
+        device_graph.write_graphviz(tmp.path, LABEL_FLAGS, TOOLTIP_FLAGS)
+        content = ReplacePoint(
+          replace_point_id,
+          Yast::Term.new(:Graph, graph_id, Opt(:notify), tmp.path, "dot")
+        )
+        Yast::UI.ReplaceWidget(replace_point_id, content)
+      ensure
+        tmp.close!
+      end
+
+      # @macro seeAbstractWidget
+      def handle
+        node = Yast::UI.QueryWidget(graph_id, :Item)
+        device = device_graph.find_device(node.to_i)
+        return nil unless device
+
+        page = find_target_page(device)
+        return nil unless page
+
+        pager.switch_page(page)
+      end
+
+    private
+
+      # @return [Devicegraph] graph to display
+      attr_reader :device_graph
+
+      # @return [CWM::TreePager] main pager used to jump to the different
+      #   partitioner sections
+      attr_reader :pager
+
+      # Id used for the main widget which is replaced with updated content on
+      # every render (see {#init})
+      def replace_point_id
+        Id(:"#{widget_id}_content")
+      end
+
+      # Id used for the Graph widget and its original empty placeholder
+      def graph_id
+        Id(:"#{widget_id}_graph")
+      end
+
+      # Find the closest partitioner page for the given device
+      #
+      # If there is a page for that device, it returns that page. Otherwise, it
+      # returns the page of the closest ancestor having such page.
+      #
+      # @return [CWM::Page, nil] nil if no appropiate page was found
+      def find_target_page(device)
+        page = pager.device_page(device)
+        return page if page
+
+        parents = device.parents
+        return nil if parents.empty?
+
+        find_ancestor_page(device)
+      end
+
+      # @see #find_target_page
+      #
+      # @return [CWM::Page, nil] nil if no appropiate page was found
+      def find_ancestor_page(device)
+        page = nil
+        device.parents.each do |parent|
+          page = find_target_page(parent)
+          break if page
+        end
+
+        page
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-4.0.82/test/y2partitioner/widgets/device_graph_with_buttons_test.rb
 
new/yast2-storage-ng-4.0.84/test/y2partitioner/widgets/device_graph_with_buttons_test.rb
--- 
old/yast2-storage-ng-4.0.82/test/y2partitioner/widgets/device_graph_with_buttons_test.rb
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/yast2-storage-ng-4.0.84/test/y2partitioner/widgets/device_graph_with_buttons_test.rb
    2018-02-07 10:51:09.000000000 +0100
@@ -0,0 +1,170 @@
+#!/usr/bin/env rspec
+# encoding: utf-8
+
+# Copyright (c) [2018] 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_relative "../test_helper"
+
+require "cwm/rspec"
+require "y2partitioner/widgets/device_graph_with_buttons"
+require "tempfile"
+
+describe Y2Partitioner::Widgets::DeviceGraphWithButtons do
+  before do
+    devicegraph_stub("complex-lvm-encrypt")
+  end
+
+  let(:device_graph) { Y2Partitioner::DeviceGraphs.instance.current }
+  let(:visual_device_graph) { double("VisualDeviceGraph") }
+  let(:xml_button) { double("SaveDeviceGraphButton") }
+  let(:gv_button) { double("SaveDeviceGraphButton") }
+  let(:pager) { double("OverviewTreePager") }
+
+  subject(:widget) { described_class.new(device_graph, pager) }
+
+  include_examples "CWM::CustomWidget"
+
+  describe "#contents" do
+    it "includes the graph and the two buttons for saving" do
+      expect(Y2Partitioner::Widgets::VisualDeviceGraph).to receive(:new)
+        .with(device_graph, pager).and_return visual_device_graph
+      expect(Y2Partitioner::Widgets::SaveDeviceGraphButton).to receive(:new)
+        .with(device_graph, :xml).and_return xml_button
+      expect(Y2Partitioner::Widgets::SaveDeviceGraphButton).to receive(:new)
+        .with(device_graph, :gv).and_return gv_button
+
+      contents = widget.contents
+
+      found = contents.nested_find { |i| i == visual_device_graph }
+      expect(found).to_not be_nil
+      found = contents.nested_find { |i| i == xml_button }
+      expect(found).to_not be_nil
+      found = contents.nested_find { |i| i == gv_button }
+      expect(found).to_not be_nil
+    end
+  end
+
+  describe Y2Partitioner::Widgets::SaveDeviceGraphButton do
+    subject(:widget) { described_class.new(device_graph, format) }
+
+    around do |example|
+      # Extra "begin" forced by rubocop
+      begin
+        @tmp_file = Tempfile.new("graph")
+        example.run
+      ensure
+        @tmp_file.close!
+      end
+    end
+
+    context "for the XML format" do
+      let(:format) { :xml }
+
+      include_examples "CWM::PushButton"
+
+      describe "#label" do
+        it "returns the correct label" do
+          expect(widget.label).to include "XML"
+        end
+      end
+
+      describe "#handle" do
+        before do
+          allow(Yast::UI).to receive(:AskForSaveFileName).and_return 
@tmp_file.path
+        end
+
+        it "exports the device graph to XML with the given file name" do
+          expect(@tmp_file.read).to be_empty
+
+          widget.handle
+          content = @tmp_file.read
+
+          expect(content).to start_with "<?xml version="
+          expect(content).to include "<name>/dev/sda4</name>"
+          expect(content).to include "<name>/dev/mapper/cr_sda4</name>"
+          expect(content).to include "<name>/dev/sdg</name>"
+          expect(content).to include 
"<uuid>abcdefgh-ijkl-mnop-qrst-uvwxyzzz</uuid>"
+        end
+
+        context "if an error is raised writing the file" do
+          before do
+            allow(device_graph).to receive(:save).and_raise Storage::Exception
+          end
+
+          it "shows a pop-up to the user" do
+            expect(Yast::Popup).to receive(:Error)
+            widget.handle
+          end
+
+          it "does nothing about the file content" do
+            widget.handle
+            expect(@tmp_file.read).to be_empty
+          end
+        end
+      end
+    end
+
+    context "for the Graphviz format" do
+      let(:format) { :gv }
+
+      include_examples "CWM::PushButton"
+
+      describe "#label" do
+        it "returns the correct label" do
+          expect(widget.label).to include "Graphviz"
+        end
+      end
+
+      describe "#handle" do
+        before do
+          allow(Yast::UI).to receive(:AskForSaveFileName).and_return 
@tmp_file.path
+        end
+
+        it "exports the device graph to Dot format with the given file name" do
+          expect(@tmp_file.read).to be_empty
+
+          widget.handle
+          content = @tmp_file.read
+
+          expect(content).to include "digraph G {"
+          expect(content).to include "label=\"/dev/sda4\""
+          expect(content).to include "label=cr_sda4"
+          expect(content).to include "label=\"/dev/sdg\""
+        end
+
+        context "if an error is raised writing the file" do
+          before do
+            allow(device_graph).to receive(:write_graphviz).and_raise 
Storage::Exception
+          end
+
+          it "shows a pop-up to the user" do
+            expect(Yast::Popup).to receive(:Error)
+            widget.handle
+          end
+
+          it "does nothing about the file content" do
+            widget.handle
+            expect(@tmp_file.read).to be_empty
+          end
+        end
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-4.0.82/test/y2partitioner/widgets/overview_test.rb 
new/yast2-storage-ng-4.0.84/test/y2partitioner/widgets/overview_test.rb
--- old/yast2-storage-ng-4.0.82/test/y2partitioner/widgets/overview_test.rb     
2018-02-01 11:13:40.000000000 +0100
+++ new/yast2-storage-ng-4.0.84/test/y2partitioner/widgets/overview_test.rb     
2018-02-07 10:51:09.000000000 +0100
@@ -97,6 +97,10 @@
 
     let(:disks_pages) { disks_pager.pages - [disks_pager.page] }
 
+    let(:device_graph_page) do
+      overview_tree.items.find { |i| 
i.page.is_a?(Y2Partitioner::Widgets::Pages::DeviceGraph) }
+    end
+
     it "has a OverviewTree widget" do
       expect(overview_tree).to_not be_nil
     end
@@ -105,6 +109,11 @@
       expect(disks_pager).to_not be_nil
     end
 
+    before do
+      allow(Yast::UI).to receive(:HasSpecialWidget).with(:Graph).and_return 
graph_available
+    end
+    let(:graph_available) { true }
+
     context "when there are disk, dasd or multipath devices" do
       let(:scenario) { "empty-dasd-and-multipath.xml" }
 
@@ -191,6 +200,22 @@
         expect(md_pages).to be_empty
       end
     end
+
+    context "when the UI supports the Graph widget (Qt)" do
+      let(:graph_available) { true }
+
+      it "includes the 'Device Graph' page" do
+        expect(device_graph_page).to_not be_nil
+      end
+    end
+
+    context "when the UI does not support the Graph widget (ncurses)" do
+      let(:graph_available) { false }
+
+      it "does not include the 'Device Graph' page" do
+        expect(device_graph_page).to be_nil
+      end
+    end
   end
 
   describe "#validate" do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-4.0.82/test/y2partitioner/widgets/pages/device_graph_test.rb
 
new/yast2-storage-ng-4.0.84/test/y2partitioner/widgets/pages/device_graph_test.rb
--- 
old/yast2-storage-ng-4.0.82/test/y2partitioner/widgets/pages/device_graph_test.rb
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/yast2-storage-ng-4.0.84/test/y2partitioner/widgets/pages/device_graph_test.rb
   2018-02-07 10:51:09.000000000 +0100
@@ -0,0 +1,81 @@
+#!/usr/bin/env rspec
+# encoding: utf-8
+
+# Copyright (c) [2018] 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_relative "../../test_helper"
+
+require "cwm/rspec"
+require "y2partitioner/widgets/pages"
+require "y2partitioner/device_graphs"
+
+describe Y2Partitioner::Widgets::Pages::DeviceGraph do
+  before do
+    devicegraph_stub("complex-lvm-encrypt")
+  end
+
+  let(:device_graph) { Y2Partitioner::DeviceGraphs.instance.current }
+
+  subject(:page) { described_class.new(pager) }
+
+  let(:pager) { double("OverviewTreePager") }
+  let(:system) { Y2Partitioner::DeviceGraphs.instance.system }
+  let(:current) { Y2Partitioner::DeviceGraphs.instance.current }
+
+  include_examples "CWM::Page"
+
+  describe "#contents" do
+    it "includes a tab for the current graph and another for the system one" do
+      expect(Y2Partitioner::Widgets::Pages::DeviceGraphTab).to receive(:new)
+        .with("Planned Devices", current, any_args)
+      expect(Y2Partitioner::Widgets::Pages::DeviceGraphTab).to receive(:new)
+        .with("Current System Devices", system, any_args)
+      page.contents
+    end
+  end
+
+  describe Y2Partitioner::Widgets::Pages::DeviceGraphTab do
+    let(:device_graph_widget) { double("DeviceGraphWithButtons") }
+    let(:device_graph) { double("Devicegraph") }
+
+    subject(:widget) { described_class.new("Label", device_graph, 
"Description", pager) }
+
+    include_examples "CWM::Tab"
+
+    describe "#label" do
+      it "returns the correct label" do
+        expect(widget.label).to eq "Label"
+      end
+    end
+
+    describe "#contents" do
+      it "includes the description and the graph widget" do
+        expect(Y2Partitioner::Widgets::DeviceGraphWithButtons).to receive(:new)
+          .with(device_graph, pager).and_return device_graph_widget
+        contents = widget.contents
+
+        found = contents.nested_find { |i| i == device_graph_widget }
+        expect(found).to_not be_nil
+        found = contents.nested_find { |i| i.respond_to?(:params) && i.params 
== ["Description"] }
+        expect(found).to_not be_nil
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-storage-ng-4.0.82/test/y2partitioner/widgets/visual_device_graph_test.rb
 
new/yast2-storage-ng-4.0.84/test/y2partitioner/widgets/visual_device_graph_test.rb
--- 
old/yast2-storage-ng-4.0.82/test/y2partitioner/widgets/visual_device_graph_test.rb
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/yast2-storage-ng-4.0.84/test/y2partitioner/widgets/visual_device_graph_test.rb
  2018-02-07 10:51:09.000000000 +0100
@@ -0,0 +1,100 @@
+#!/usr/bin/env rspec
+# encoding: utf-8
+
+# Copyright (c) [2018] 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_relative "../test_helper"
+
+require "cwm/rspec"
+require "y2partitioner/widgets/visual_device_graph"
+require "y2partitioner/widgets/overview"
+
+describe Y2Partitioner::Widgets::VisualDeviceGraph do
+  before do
+    devicegraph_stub("complex-lvm-encrypt")
+  end
+
+  let(:device_graph) { Y2Partitioner::DeviceGraphs.instance.current }
+  let(:pager) { Y2Partitioner::Widgets::OverviewTreePager.new("hostname") }
+
+  subject(:widget) { described_class.new(device_graph, pager) }
+
+  include_examples "CWM::CustomWidget"
+
+  describe "#handle" do
+    before do
+      Y2Storage::Filesystems::Nfs.create(device_graph, "new", "/device")
+      allow(Yast::UI).to receive(:QueryWidget).and_return item
+    end
+
+    context "when there is no device with the clicked sid" do
+      let(:item) { "999" }
+
+      it "doesn't change the current section" do
+        expect(pager).to_not receive(:switch_page)
+        widget.handle
+      end
+    end
+
+    context "when an NFS device is clicked" do
+      let(:item) { device_graph.nfs_mounts.first.sid.to_s }
+
+      it "switches to the NFS section" do
+        expect(pager).to receive(:switch_page) do |page|
+          expect(page.label).to eq "NFS"
+        end
+        widget.handle
+      end
+    end
+
+    context "when a device with its own page is clicked" do
+      let(:partition) { device_graph.find_by_name("/dev/sda1") }
+      let(:item) { partition.sid.to_s }
+
+      it "switches to the corresponding section" do
+        expect(pager).to receive(:switch_page) do |page|
+          expect(page.label).to eq "sda1"
+        end
+        widget.handle
+      end
+    end
+
+    context "when a file system is clicked" do
+      let(:device) { device_graph.find_by_name("/dev/vg0/lv1") }
+      let(:item) { device.filesystem.sid.to_s }
+
+      it "switches to the section of the host device" do
+        expect(pager).to receive(:switch_page) do |page|
+          expect(page.label).to eq "lv1"
+        end
+        widget.handle
+      end
+    end
+  end
+
+  describe "#init" do
+    it "updates the content of the graph widget" do
+      allow(Yast::Term).to receive(:new)
+      expect(Yast::Term).to receive(:new).with(:Graph, any_args)
+      expect(Yast::UI).to receive(:ReplaceWidget)
+      widget.init
+    end
+  end
+end


Reply via email to