Hello community, here is the log from the commit of package yast2 for openSUSE:Factory checked in at 2015-05-23 12:56:35 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/yast2 (Old) and /work/SRC/openSUSE:Factory/.yast2.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yast2" Changes: -------- --- /work/SRC/openSUSE:Factory/yast2/yast2.changes 2015-05-19 23:23:24.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.yast2.new/yast2.changes 2015-05-23 12:56:36.000000000 +0200 @@ -1,0 +2,13 @@ +Fri May 22 12:32:27 UTC 2015 - [email protected] + +- InstExtensionImage: add block variant for loading extension + (needed for FATE#317900) +- 3.1.124 + +------------------------------------------------------------------- +Tue May 19 04:56:13 UTC 2015 - [email protected] + +- Add a class FsSnapshot for managing filesystem snapshots + (fate#317973). + +------------------------------------------------------------------- Old: ---- yast2-3.1.123.tar.bz2 New: ---- yast2-3.1.124.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yast2.spec ++++++ --- /var/tmp/diff_new_pack.8lYAtJ/_old 2015-05-23 12:56:36.000000000 +0200 +++ /var/tmp/diff_new_pack.8lYAtJ/_new 2015-05-23 12:56:36.000000000 +0200 @@ -17,7 +17,7 @@ Name: yast2 -Version: 3.1.123 +Version: 3.1.124 Release: 0 Url: https://github.com/yast/yast-yast2 ++++++ yast2-3.1.123.tar.bz2 -> yast2-3.1.124.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/library/control/Makefile.am new/yast2-3.1.124/library/control/Makefile.am --- old/yast2-3.1.123/library/control/Makefile.am 2015-05-18 17:02:13.000000000 +0200 +++ new/yast2-3.1.124/library/control/Makefile.am 2015-05-22 15:51:11.000000000 +0200 @@ -2,4 +2,4 @@ # Makefile.am for xml/module # -SUBDIRS = doc src testsuite +SUBDIRS = doc src test testsuite diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/library/control/src/modules/InstExtensionImage.rb new/yast2-3.1.124/library/control/src/modules/InstExtensionImage.rb --- old/yast2-3.1.123/library/control/src/modules/InstExtensionImage.rb 2015-05-18 17:02:13.000000000 +0200 +++ new/yast2-3.1.124/library/control/src/modules/InstExtensionImage.rb 2015-05-22 15:51:11.000000000 +0200 @@ -337,6 +337,29 @@ nil end + # Load a rpm package from the media into the inst-sys and ensure its + # unloading after end of block. + # @param [String] package to load + # @param [Proc] Block to be yield + # @raises [RuntimeError] when package loading failed + # + # @example + # InstExtensionImage.with_extension("snapper") do + # WFM.Execute(path(".local.bash"), "snapper magic") + # end + # + def with_extension(package, &block) + loading_msg = format(_("Loading to memory package '%s'"), package) + res = LoadExtension(package, loading_msg) + raise "Failed to load package. Please check logs." unless res + begin + block.call + ensure + unloading_msg = format(_("Removing from memory package '%s'"), package) + UnLoadExtension(package, unloading_msg) + end + end + # Load a rpm package from the media into the inst-sys # @param [String] package The path to package to be loaded (by default, # the package is expected in the /boot/<arch>/ directory of the media diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/library/control/test/InstExtensionImage_test.rb new/yast2-3.1.124/library/control/test/InstExtensionImage_test.rb --- old/yast2-3.1.123/library/control/test/InstExtensionImage_test.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-3.1.124/library/control/test/InstExtensionImage_test.rb 2015-05-22 15:51:11.000000000 +0200 @@ -0,0 +1,133 @@ +#! /usr/bin/env rspec + +require_relative "test_helper" + +Yast.import "InstExtensionImage" + +describe Yast::InstExtensionImage do + subject { Yast::InstExtensionImage } + + describe ".LoadExtension" do + before do + # clean internal cache of already loaded extension + subject.instance_variable_set("@integrated_extensions", []) + end + it "returns false if package is nil" do + expect(subject.LoadExtension(nil, "msg")).to eq false + end + + it "returns false if package is \"\"" do + expect(subject.LoadExtension("", "msg")).to eq false + end + + it "returns true immediately if package is already loaded" do + subject.instance_variable_set("@integrated_extensions", ["snapper"]) + expect(subject.LoadExtension("snapper", "msg")).to eq true + end + + it "shows message as feedback when loading package" do + expect(Yast::Popup).to receive(:ShowFeedback).with("", "msg") + + subject.LoadExtension("snapper", "msg") + end + + it "calls extend CLI with given package" do + expect(Yast::WFM).to receive(:Execute) + .with(path(".local.bash_output"), "extend 'snapper'") + .and_return("exit" => 0) + + subject.LoadExtension("snapper", "msg") + end + + it "returns false if extend CLI failed" do + expect(Yast::WFM).to receive(:Execute) + .with(path(".local.bash_output"), "extend 'snapper'") + .and_return("exit" => 1) + + expect(subject.LoadExtension("snapper", "msg")).to eq false + end + end + + describe ".UnLoadExtension" do + before do + # set in internal cache that snapper is already loaded + subject.instance_variable_set("@integrated_extensions", ["snapper"]) + end + it "returns false if package is nil" do + expect(subject.UnLoadExtension(nil, "msg")).to eq false + end + + it "returns false if package is \"\"" do + expect(subject.UnLoadExtension("", "msg")).to eq false + end + + it "returns true immediately if package is already unloaded" do + subject.instance_variable_set("@integrated_extensions", []) + expect(subject.UnLoadExtension("snapper", "msg")).to eq true + end + + it "shows message as feedback when unloading package" do + expect(Yast::Popup).to receive(:ShowFeedback).with("", "msg") + + subject.UnLoadExtension("snapper", "msg") + end + + it "calls extend CLI with given package" do + expect(Yast::WFM).to receive(:Execute) + .with(path(".local.bash_output"), "extend -r 'snapper'") + .and_return("exit" => 0) + + subject.UnLoadExtension("snapper", "msg") + end + + it "returns false if extend CLI failed" do + expect(Yast::WFM).to receive(:Execute) + .with(path(".local.bash_output"), "extend -r 'snapper'") + .and_return("exit" => 1) + + expect(subject.UnLoadExtension("snapper", "msg")).to eq false + end + end + + describe ".with_extension" do + before do + # clean internal cache of already loaded extension + subject.instance_variable_set("@integrated_extensions", []) + end + + it "loads package, executes block and unload package" do + expect(Yast::WFM).to receive(:Execute) + .with(path(".local.bash_output"), "extend 'snapper'") + .and_return("exit" => 0) + expect(Yast::WFM).to receive(:Execute) + .with(path(".local.bash_output"), "extend -r 'snapper'") + .and_return("exit" => 0) + + res = nil + subject.with_extension("snapper") do + res = true + end + + expect(res).to eq true + end + + it "raises exception if package loading fails" do + expect(Yast::WFM).to receive(:Execute) + .with(path(".local.bash_output"), "extend 'snapper'") + .and_return("exit" => 1) + + expect { subject.with_extension("snapper") {} }.to raise_error + end + + it "unloads extension even if block raises exception" do + expect(Yast::WFM).to receive(:Execute) + .with(path(".local.bash_output"), "extend 'snapper'") + .and_return("exit" => 0) + expect(Yast::WFM).to receive(:Execute) + .with(path(".local.bash_output"), "extend -r 'snapper'") + .and_return("exit" => 0) + + expect { subject.with_extension("snapper") { raise "expected" } }.to raise_error + end + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/library/control/test/Makefile.am new/yast2-3.1.124/library/control/test/Makefile.am --- old/yast2-3.1.123/library/control/test/Makefile.am 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-3.1.124/library/control/test/Makefile.am 2015-05-22 15:51:11.000000000 +0200 @@ -0,0 +1,7 @@ +TESTS = \ + InstExtensionImage_test.rb + +TEST_EXTENSIONS = .rb +RB_LOG_COMPILER = rspec +VERBOSE = 1 +EXTRA_DIST = $(TESTS) test_helper.rb diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/library/control/test/test_helper.rb new/yast2-3.1.124/library/control/test/test_helper.rb --- old/yast2-3.1.123/library/control/test/test_helper.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-3.1.124/library/control/test/test_helper.rb 2015-05-22 15:51:11.000000000 +0200 @@ -0,0 +1 @@ +require_relative "../../../test/test_helper.rb" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/library/system/src/Makefile.am new/yast2-3.1.124/library/system/src/Makefile.am --- old/yast2-3.1.123/library/system/src/Makefile.am 2015-05-18 17:02:13.000000000 +0200 +++ new/yast2-3.1.124/library/system/src/Makefile.am 2015-05-22 15:51:11.000000000 +0200 @@ -29,7 +29,8 @@ ylibdir = @ylibdir@/yast2 ylib_DATA = \ - lib/yast2/hw_detection.rb + lib/yast2/hw_detection.rb \ + lib/yast2/fs_snapshot.rb EXTRA_DIST = $(module_DATA) $(client_DATA) $(ynclude_DATA) $(scrconf_DATA) $(desktop_DATA) $(ylib_DATA) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/library/system/src/lib/yast2/fs_snapshot.rb new/yast2-3.1.124/library/system/src/lib/yast2/fs_snapshot.rb --- old/yast2-3.1.123/library/system/src/lib/yast2/fs_snapshot.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-3.1.124/library/system/src/lib/yast2/fs_snapshot.rb 2015-05-22 15:51:11.000000000 +0200 @@ -0,0 +1,211 @@ +# encoding: utf-8 + +# *************************************************************************** +# +# Copyright (c) 2015 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 Novell, Inc. +# +# To contact Novell about this file by physical or electronic mail, +# you may find current contact information at www.novell.com +# +# *************************************************************************** +# File: fs_snapshot.rb +# +# Authors: +# Imobach Gonzalez Sosa <[email protected]> + +require "yast" +require "date" + +module Yast2 + # Represents the fact that Snapper is not configured for "/" (root). + class SnapperNotConfigured < StandardError + def initialize + super "Programming error: Snapper is not configured yet." + end + end + + # Represents that does not exist a suitable 'pre' snapshot for a new 'post' + # snapshot. + class PreviousSnapshotNotFound < StandardError + def initialize + super "Previous snapshot was not found." + end + end + + # Represents the fact that the snapshot could not be created. + class SnapshotCreationFailed < StandardError + def initialize + super "Filesystem snapshot could not be created." + end + end + + # Class for managing filesystem snapshots. It's important to note that this + # class is intended to be used during installation/update so it uses the + # Snapper's CLI because the DBus interface is not available at that time. + class FsSnapshot + include Yast::Logger + + FIND_CONFIG_CMD = "/usr/bin/snapper --no-dbus list-configs | grep \"^root \" >/dev/null" + CREATE_SNAPSHOT_CMD = "/usr/lib/snapper/installation-helper --step 5 --snapshot-type %s --description \"%s\"" + LIST_SNAPSHOTS_CMD = "LANG=en_US.UTF-8 /usr/bin/snapper --no-dbus list" + VALID_LINE_REGEX = /\A\w+\s+\| \d+/ + + attr_reader :number, :snapshot_type, :previous_number, :timestamp, :user, + :cleanup_algo, :description + + # Determines whether snapper is configured or not + # + # @return [true,false] true if it's configured; false otherwise. + def self.configured? + out = Yast::SCR.Execute(Yast::Path.new(".target.bash_output"), FIND_CONFIG_CMD) + log.info("Checking if Snapper is configured: \"#{FIND_CONFIG_CMD}\" returned: #{out}") + out["exit"] == 0 + end + + # Creates a new 'single' snapshot + # + # @param description [String] Snapshot's description. + # @return [FsSnapshot] The created snapshot. + # + # @see FsSnapshot.create + def self.create_single(description) + create(:single, description) + end + + # Creates a new 'pre' snapshot + # + # @param description [String] Snapshot's description. + # @return [FsSnapshot] The created snapshot. + # + # @see FsSnapshot.create + def self.create_pre(description) + create(:pre, description) + end + + # Creates a new 'post' snapshot + # + # Each 'post' snapshot corresponds with a 'pre' one. + # + # @param description [String] Snapshot's description. + # @param previous_number [Fixnum] Number of the previous snapshot + # @return [FsSnapshot] The created snapshot. + # + # @see FsSnapshot.create + def self.create_post(description, previous_number) + previous = find(previous_number) + if previous + create(:post, description, previous) + else + log.error "Previous filesystem snapshot was not found" + raise PreviousSnapshotNotFound + end + end + + # Creates a new snapshot + # + # It raises an exception if Snapper is not configured or if snapshot + # creation fails. + # + # @param snapshot_type [Symbol] Snapshot's type: :pre, :post or :single. + # @param description [String] Snapshot's description. + # @param previous [FsSnashot] Previous snapshot. + # @return [FsSnapshot] The created snapshot if the operation was + # successful. + def self.create(snapshot_type, description, previous = nil) + raise SnapperNotConfigured unless configured? + + cmd = format(CREATE_SNAPSHOT_CMD, snapshot_type, description) + cmd << format(" --pre-num %s", previous.number) if previous + out = Yast::SCR.Execute(Yast::Path.new(".target.bash_output"), cmd) + if out["exit"] == 0 + find(out["stdout"].to_i) # The CREATE_SNAPSHOT_CMD returns the number of the new snapshot. + else + log.error "Snapshot could not be created: #{cmd} returned: #{out}" + raise SnapshotCreationFailed + end + end + private_class_method :create + + # Returns all snapshots + # + # It raises an exception if Snapper is not configured. + # + # @return [Array<FsSnapshot>] All snapshots that exist in the system. + def self.all + raise SnapperNotConfigured unless configured? + + out = Yast::SCR.Execute(Yast::Path.new(".target.bash_output"), LIST_SNAPSHOTS_CMD) + lines = out["stdout"].lines.grep(VALID_LINE_REGEX) # relevant lines from output. + log.info("Retrieving snapshots list: #{LIST_SNAPSHOTS_CMD} returned: #{out}") + lines.map do |line| + data = line.split("|").map(&:strip) + begin + timestamp = DateTime.parse(data[3]) + rescue ArgumentError + log.warn("Error when parsing date/time: #{timestamp}") + timestamp = nil + end + previous_number = data[2] == "" ? nil : data[2].to_i + new(data[1].to_i, data[0].to_sym, previous_number, timestamp, data[4], + data[5].to_sym, data[6]) + end + end + + # Finds a snapshot by its number + # + # It raises an exception if Snapper is not configured. + # + # @param nubmer [Fixnum] Number of the snapshot to search for. + # @return [FsSnapshot,nil] The snapshot with the number +number+ if found. + # Otherwise, it returns nil. + # @see FsSnapshot.all + def self.find(number) + all.find { |s| s.number == number } + end + + # FsSnapshot constructor + # + # This method is not intended to be called by users of FsSnapshot class. + # Instead, class methods must be used. + # + # @param number [Fixnum] Snapshot's number. + # @param snapshot_type [Symbol] Snapshot's type: :pre, :post or :single. + # @param previous_number [Fixnum] Previous snapshot's number. + # @param timestamp [DateTime] Timestamp + # @param user [String] Snapshot's owner username. + # @param cleanup_algo [String] Clean-up algorithm. + # @param description [String] Snapshot's description. + # @return [FsSnapshot] New FsSnapshot object. + def initialize(number, snapshot_type, previous_number, timestamp, user, cleanup_algo, description) + @number = number + @snapshot_type = snapshot_type + @previous_number = previous_number + @timestamp = timestamp + @user = user + @cleanup_algo = cleanup_algo + @description = description + end + + private_class_method :new + + # Returns the previous snapshot + # + # @return [FsSnapshot, nil] Object representing the previous snapshot. + def previous + @previous ||= @previous_number ? FsSnapshot.find(@previous_number) : nil + end + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/library/system/test/Makefile.am new/yast2-3.1.124/library/system/test/Makefile.am --- old/yast2-3.1.123/library/system/test/Makefile.am 2015-05-18 17:02:13.000000000 +0200 +++ new/yast2-3.1.124/library/system/test/Makefile.am 2015-05-22 15:51:11.000000000 +0200 @@ -1,6 +1,7 @@ TESTS = \ kernel_test.rb \ - hw_detection_test.rb + hw_detection_test.rb \ + fs_snapshot_test.rb TEST_EXTENSIONS = .rb RB_LOG_COMPILER = rspec diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/library/system/test/fixtures/empty-snapper-list.txt new/yast2-3.1.124/library/system/test/fixtures/empty-snapper-list.txt --- old/yast2-3.1.123/library/system/test/fixtures/empty-snapper-list.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-3.1.124/library/system/test/fixtures/empty-snapper-list.txt 2015-05-22 15:51:11.000000000 +0200 @@ -0,0 +1,2 @@ +Type | # | Pre # | Date | User | Cleanup | Description | Userdata +-------+----+-------+----------------------------------+------+---------+--------------+-------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/library/system/test/fixtures/snapper-list.txt new/yast2-3.1.124/library/system/test/fixtures/snapper-list.txt --- old/yast2-3.1.123/library/system/test/fixtures/snapper-list.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-3.1.124/library/system/test/fixtures/snapper-list.txt 2015-05-22 15:51:11.000000000 +0200 @@ -0,0 +1,7 @@ +Type | # | Pre # | Date | User | Cleanup | Description | Userdata +-------+----+-------+----------------------------------+------+---------+--------------+-------------- +single | 0 | | | root | | current | +pre | 1 | | Wed 13 May 2015 04:14:14 PM WEST | root | number | zypp(y2base) | important=no +pre | 3 | | Wed 13 May 2015 05:01:47 PM WEST | root | number | zypp(zypper) | important=no +post | 4 | 3 | Wed 13 May 2015 05:03:13 PM WEST | root | number | zypp(zypper) | important=no +single | 5 | | Wed 13 May 2015 05:11:25 PM WEST | root | | | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/library/system/test/fs_snapshot_test.rb new/yast2-3.1.124/library/system/test/fs_snapshot_test.rb --- old/yast2-3.1.123/library/system/test/fs_snapshot_test.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-3.1.124/library/system/test/fs_snapshot_test.rb 2015-05-22 15:51:11.000000000 +0200 @@ -0,0 +1,325 @@ +#!/usr/bin/env rspec + +require_relative "test_helper" +require "yast2/fs_snapshot" + +describe Yast2::FsSnapshot do + def logger + described_class.log + end + + FIND_CONFIG = "/usr/bin/snapper --no-dbus list-configs | grep \"^root \" >/dev/null" + LIST_SNAPSHOTS = "LANG=en_US.UTF-8 /usr/bin/snapper --no-dbus list" + + describe ".configured?" do + before do + allow(Yast::SCR).to receive(:Execute) + .with(path(".target.bash_output"), FIND_CONFIG) + .and_return("stdout" => "", "exit" => find_code) + end + + context "when snapper's configuration does not exist" do + let(:find_code) { 1 } + + it "returns false" do + expect(logger).to receive(:info).with(/Checking if Snapper is configured/) + expect(described_class.configured?).to eq(false) + end + end + + context "when snapper's configuration exists" do + let(:find_code) { 0 } + + it "returns false" do + expect(described_class.configured?).to eq(true) + end + end + end + + describe ".create_single" do + CREATE_SINGLE_SNAPSHOT = "/usr/lib/snapper/installation-helper --step 5 "\ + "--snapshot-type single --description \"some-description\"" + + before do + allow(Yast2::FsSnapshot).to receive(:configured?).and_return(configured) + end + + context "when snapper is configured" do + let(:configured) { true } + + before do + allow(Yast::SCR).to receive(:Execute) + .with(path(".target.bash_output"), CREATE_SINGLE_SNAPSHOT) + .and_return(output) + end + + context "when snapshot creation fails" do + let(:output) { { "stdout" => "", "exit" => 1 } } + + it "logs the error and returns nil" do + expect(logger).to receive(:error).with(/Snapshot could not be created/) + expect { described_class.create_single("some-description") } + .to raise_error(Yast2::SnapshotCreationFailed) + end + end + + context "when snapshot creation is successful" do + let(:output) { { "stdout" => "2", "exit" => 0 } } + let(:dummy_snapshot) { double("snapshot") } + + it "returns the created snapshot" do + expect(described_class).to receive(:find).with(2) + .and_return(dummy_snapshot) + snapshot = described_class.create_single("some-description") + expect(snapshot).to be(dummy_snapshot) + end + end + end + + context "when snapper is not configured" do + let(:configured) { false } + + it "raises an exception" do + expect { described_class.create_single("some-description") } + .to raise_error(Yast2::SnapperNotConfigured) + end + end + end + + describe ".create_pre" do + CREATE_PRE_SNAPSHOT = "/usr/lib/snapper/installation-helper --step 5 "\ + "--snapshot-type pre --description \"some-description\"" + + before do + allow(Yast2::FsSnapshot).to receive(:configured?).and_return(configured) + end + + context "when snapper is configured" do + let(:configured) { true } + + before do + allow(Yast::SCR).to receive(:Execute) + .with(path(".target.bash_output"), CREATE_PRE_SNAPSHOT) + .and_return(output) + end + + context "when snapshot creation fails" do + let(:output) { { "stdout" => "", "exit" => 1 } } + + it "logs the error and returns nil" do + expect(logger).to receive(:error).with(/Snapshot could not be created/) + expect { described_class.create_pre("some-description") } + .to raise_error(Yast2::SnapshotCreationFailed) + end + end + + context "when snapshot creation is successful" do + let(:output) { { "stdout" => "2", "exit" => 0 } } + let(:dummy_snapshot) { double("snapshot") } + + it "returns the created snapshot" do + expect(described_class).to receive(:find).with(2) + .and_return(dummy_snapshot) + snapshot = described_class.create_pre("some-description") + expect(snapshot).to be(dummy_snapshot) + end + end + end + + context "when snapper is not configured" do + let(:configured) { false } + + it "raises an exception" do + expect { described_class.create_pre("some-description") } + .to raise_error(Yast2::SnapperNotConfigured) + end + end + end + + describe ".create_post" do + CREATE_POST_SNAPSHOT = "/usr/lib/snapper/installation-helper --step 5 "\ + "--snapshot-type post --description \"some-description\" --pre-num 2" + + before do + allow(Yast2::FsSnapshot).to receive(:configured?).and_return(configured) + end + + context "when snapper is configured" do + let(:configured) { true } + + let(:pre_snapshot) { double("snapshot", snapshot_type: :pre, number: 2) } + let(:dummy_snapshot) { double("snapshot") } + let(:snapshots) { [pre_snapshot] } + let(:output) { { "stdout" => "3", "exit" => 0 } } + + before do + allow(Yast::SCR).to receive(:Execute) + .with(path(".target.bash_output"), CREATE_POST_SNAPSHOT) + .and_return(output) + allow(Yast2::FsSnapshot).to receive(:all) + .and_return(snapshots) + end + + context "when previous snapshot exists" do + let(:snapshots) { [pre_snapshot] } + + context "when snapshot creation is successful" do + it "returns the created snapshot" do + allow(Yast2::FsSnapshot).to receive(:find).with(pre_snapshot.number) + .and_return(pre_snapshot) + expect(Yast2::FsSnapshot).to receive(:find).with(3) + .and_return(dummy_snapshot) + expect(described_class.create_post("some-description", pre_snapshot.number)) + .to be(dummy_snapshot) + end + end + + context "when snapshot creation fails" do + let(:output) { { "stdout" => "", "exit" => 1 } } + + it "logs the error and raises an exception" do + expect(logger).to receive(:error).with(/Snapshot could not be created/) + expect { described_class.create_post("some-description", pre_snapshot.number) } + .to raise_error(Yast2::SnapshotCreationFailed) + end + end + end + + context "when previous snapshot does not exist" do + it "logs the error and raises an exception" do + expect(logger).to receive(:error).with(/Previous filesystem snapshot was not found/) + expect { described_class.create_post("some-description", 100) } + .to raise_error(Yast2::PreviousSnapshotNotFound) + end + end + end + + context "when snapper is not configured" do + let(:configured) { false } + + it "raises an exception" do + expect { described_class.create_post("some-description", 1) } + .to raise_error(Yast2::SnapperNotConfigured) + end + end + end + + describe ".all" do + before do + allow(Yast2::FsSnapshot).to receive(:configured?).and_return(configured) + end + + context "when snapper is configured" do + let(:configured) { true } + let(:output) { File.read(output_path) } + + before do + allow(Yast::SCR).to receive(:Execute) + .with(path(".target.bash_output"), LIST_SNAPSHOTS) + .and_return("stdout" => output, "exit" => 0) + end + + context "given some snapshots exist" do + let(:output_path) { File.expand_path("../fixtures/snapper-list.txt", __FILE__) } + + it "should return the snapshots and log about how many were found" do + expect(logger).to receive(:info).with(/Retrieving snapshots list/) + snapshots = described_class.all + expect(snapshots).to be_kind_of(Array) + expect(snapshots.size).to eq(5) + end + end + + context "given no snapshots exist" do + let(:output_path) { File.expand_path("../fixtures/empty-snapper-list.txt", __FILE__) } + + it "should return an empty array" do + expect(described_class.all).to eq([]) + end + end + end + + context "when snapper is not configured" do + let(:configured) { false } + + it "raises an exception" do + expect { described_class.all } + .to raise_error(Yast2::SnapperNotConfigured) + end + end + end + + describe ".find" do + before do + allow(Yast2::FsSnapshot).to receive(:configured?).and_return(configured) + end + + context "when snapper is configured" do + let(:configured) { true } + let(:output) { File.read(output_path) } + let(:output_path) { File.expand_path("../fixtures/snapper-list.txt", __FILE__) } + + before do + allow(Yast::SCR).to receive(:Execute) + .with(path(".target.bash_output"), LIST_SNAPSHOTS) + .and_return("stdout" => output, "exit" => 0) + end + + context "when a snapshot with that number exists" do + it "should return the snapshot" do + snapshot = described_class.find(4) + expect(snapshot.number).to eq(4) + expect(snapshot.snapshot_type).to eq(:post) + expect(snapshot.previous_number).to eq(3) + expect(snapshot.timestamp).to eq(DateTime.parse("Wed 13 May 2015 05:03:13 PM WEST")) + expect(snapshot.user).to eq("root") + expect(snapshot.cleanup_algo).to eq(:number) + expect(snapshot.description).to eq("zypp(zypper)") + end + end + + context "when a snapshot with that number does not exists" do + it "should return nil" do + expect(described_class.find(100)).to be_nil + end + end + end + + context "when snapper is not configured" do + let(:configured) { false } + + it "raises an exception" do + expect { described_class.find(1) } + .to raise_error(Yast2::SnapperNotConfigured) + end + end + end + + describe "#previous" do + let(:output) { File.read(output_path) } + let(:output_path) { File.expand_path("../fixtures/snapper-list.txt", __FILE__) } + + before do + allow(Yast2::FsSnapshot).to receive(:configured?).and_return(true) + allow(Yast::SCR).to receive(:Execute) + .with(path(".target.bash_output"), LIST_SNAPSHOTS) + .and_return("stdout" => output, "exit" => 0) + end + + context "given a previous snapshot" do + subject(:fs_snapshot) { Yast2::FsSnapshot.find(4) } + + it "returns the previous snapshot" do + expect(fs_snapshot.previous.number).to eq(3) + end + end + + context "given no previous snapshot" do + subject(:fs_snapshot) { Yast2::FsSnapshot.find(3) } + + it "returns nil" do + expect(fs_snapshot.previous).to be_nil + end + end + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/package/yast2.changes new/yast2-3.1.124/package/yast2.changes --- old/yast2-3.1.123/package/yast2.changes 2015-05-18 17:02:13.000000000 +0200 +++ new/yast2-3.1.124/package/yast2.changes 2015-05-22 15:51:11.000000000 +0200 @@ -1,4 +1,17 @@ ------------------------------------------------------------------- +Fri May 22 12:32:27 UTC 2015 - [email protected] + +- InstExtensionImage: add block variant for loading extension + (needed for FATE#317900) +- 3.1.124 + +------------------------------------------------------------------- +Tue May 19 04:56:13 UTC 2015 - [email protected] + +- Add a class FsSnapshot for managing filesystem snapshots + (fate#317973). + +------------------------------------------------------------------- Mon May 18 10:32:24 CEST 2015 - [email protected] - Making SuSEFirewallProposal.propose_iscsi function public diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-3.1.123/package/yast2.spec new/yast2-3.1.124/package/yast2.spec --- old/yast2-3.1.123/package/yast2.spec 2015-05-18 17:02:13.000000000 +0200 +++ new/yast2-3.1.124/package/yast2.spec 2015-05-22 15:51:11.000000000 +0200 @@ -17,7 +17,7 @@ Name: yast2 -Version: 3.1.123 +Version: 3.1.124 Release: 0 URL: https://github.com/yast/yast-yast2
