Hello community, here is the log from the commit of package yast2 for openSUSE:Factory checked in at 2020-07-21 15:47:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/yast2 (Old) and /work/SRC/openSUSE:Factory/.yast2.new.3592 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yast2" Tue Jul 21 15:47:46 2020 rev:489 rq:822007 version:4.3.15 Changes: -------- --- /work/SRC/openSUSE:Factory/yast2/yast2.changes 2020-07-13 09:06:25.316227617 +0200 +++ /work/SRC/openSUSE:Factory/.yast2.new.3592/yast2.changes 2020-07-21 15:49:10.428205421 +0200 @@ -1,0 +2,9 @@ +Thu Jul 16 12:48:24 UTC 2020 - Ancor Gonzalez Sosa <[email protected]> + +- Better management of libzypp repovars (eg. those enclosed in + curly brackets) introducing the new Y2Packager::ZyppUrl class +- Do not crash during the upgrade process if some repository URL + cannot be parsed (bsc#1172867) +- 4.3.15 + +------------------------------------------------------------------- Old: ---- yast2-4.3.14.tar.bz2 New: ---- yast2-4.3.15.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yast2.spec ++++++ --- /var/tmp/diff_new_pack.PVDPGT/_old 2020-07-21 15:49:11.512206761 +0200 +++ /var/tmp/diff_new_pack.PVDPGT/_new 2020-07-21 15:49:11.516206766 +0200 @@ -17,7 +17,7 @@ Name: yast2 -Version: 4.3.14 +Version: 4.3.15 Release: 0 Summary: YaST2 Main Package License: GPL-2.0-only ++++++ yast2-4.3.14.tar.bz2 -> yast2-4.3.15.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-4.3.14/.github/workflows/tests.yml new/yast2-4.3.15/.github/workflows/tests.yml --- old/yast2-4.3.14/.github/workflows/tests.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-4.3.15/.github/workflows/tests.yml 2020-07-21 08:58:01.000000000 +0200 @@ -0,0 +1,22 @@ + +# See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions + +name: CI + +on: [push, pull_request] + +jobs: + Tests: + runs-on: ubuntu-latest + container: registry.opensuse.org/yast/head/containers/yast-ruby:latest + + steps: + + - name: Git Checkout + uses: actions/checkout@v1 + + - name: Inspect Installed Packages + run: rpm -qa | sort + + - name: Rubocop, Tests, Package Build + run: yast-travis-ruby diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-4.3.14/README.md new/yast2-4.3.15/README.md --- old/yast2-4.3.14/README.md 2020-07-10 16:29:19.000000000 +0200 +++ new/yast2-4.3.15/README.md 2020-07-21 08:58:01.000000000 +0200 @@ -2,6 +2,7 @@ ========================== [](https://travis-ci.org/yast/yast-yast2) +[](https://github.com/yast/yast-yast2/actions?query=workflow%3ACI) [](https://coveralls.io/r/yast/yast-yast2?branch=master) [](https://ci.opensuse.org/view/Yast/job/yast-yast2-master/) [](https://codeclimate.com/github/yast/yast-yast2) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-4.3.14/doc/desktop_file.md new/yast2-4.3.15/doc/desktop_file.md --- old/yast2-4.3.14/doc/desktop_file.md 2020-07-10 16:29:19.000000000 +0200 +++ new/yast2-4.3.15/doc/desktop_file.md 2020-07-21 08:58:01.000000000 +0200 @@ -81,7 +81,7 @@ values are `list` and `map`. Default value is `map`. * *X-SuSE-YaST-AutoInstResource* Specifies top level XML node under which is located - module specific configuration in AutoYaST profile. + module specific configuration in AutoYaST profile. By default it is {module_name}. * *X-SuSE-YaST-AutoInstResourceAliases* Specifies a list of alternative names for the top level XML node. It is used to keep backward compatibility: for diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-4.3.14/library/packages/src/lib/y2packager/repository.rb new/yast2-4.3.15/library/packages/src/lib/y2packager/repository.rb --- old/yast2-4.3.14/library/packages/src/lib/y2packager/repository.rb 2020-07-10 16:29:19.000000000 +0200 +++ new/yast2-4.3.15/library/packages/src/lib/y2packager/repository.rb 2020-07-21 08:58:01.000000000 +0200 @@ -10,7 +10,7 @@ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. # ------------------------------------------------------------------------------ -require "uri" +require "y2packager/zypp_url" require "y2packager/product" require "y2packager/resolvable" @@ -37,17 +37,11 @@ class Repository Yast.import "Pkg" - # Repository schemes considered local (see #local?) - # https://github.com/openSUSE/libzypp/blob/a7a038aeda1ad6d9e441e7d3755612aa83320dce/zypp/Url.cc#L458 - LOCAL_SCHEMES = [:cd, :dvd, :dir, :hd, :iso, :file].freeze - # @return [Fixnum] Repository ID attr_reader :repo_id # @return [String] Repository name attr_reader :name - # @return [URI::Generic] Repository URL (expanded) - attr_reader :url - # @return [URI::Generic] Raw repository URL (unexpanded) + # @return [ZyppUrl] Repository URL attr_reader :raw_url # @return [String] Product directory attr_reader :product_dir @@ -100,22 +94,21 @@ new(repo_id: repo_id, repo_alias: repo_data["alias"], enabled: repo_data["enabled"], name: repo_data["name"], autorefresh: repo_data["autorefresh"], - url: URI(repo_data["url"]), raw_url: URI(repo_data["raw_url"]), - product_dir: repo_data["product_dir"]) + url: repo_data["raw_url"], product_dir: repo_data["product_dir"]) end # Add a repository # # @param name [String] Name - # @param url [URI::Generic] Repository URL + # @param url [URI::Generic, ZyppUrl] Repository URL # @param product_dir [String] Product directory # @param enabled [Boolean] Is the repository enabled? # @param autorefresh [Boolean] Is auto-refresh enabled for this repository? # @return [Y2Packager::Repository,nil] New repository or nil if creation failed def create(name:, url:, product_dir: "", enabled: true, autorefresh: true) repo_id = Yast::Pkg.RepositoryAdd( - "name" => name, "base_urls" => [url], "enabled" => enabled, "autorefresh" => autorefresh, - "prod_dir" => product_dir + "name" => name, "base_urls" => [url.to_s], "enabled" => enabled, + "autorefresh" => autorefresh, "prod_dir" => product_dir ) repo_id ? find(repo_id) : nil @@ -124,11 +117,16 @@ # Constructor # + # @note This class calculates the expanded URL ({#url}) out of the unexpanded version + # ({#raw_url}), so there is no need to provide both versions in the constructor. Still, + # both `:url` and `:raw_url` are accepted for backwards compatibility. If `:raw_url` + # is provided, `:url` will be ignored (it can be calculated at any point). + # # @param repo_alias [String] Repository alias (unique identifier) # @param repo_id [Fixnum] Repository ID # @param name [String] Name - # @param url [URI::Generic] Repository URL (expanded) - # @param raw_url [URI::Generic] Optional raw repository URL (unexpanded) + # @param url [URI::Generic, ZyppUrl] Repository URL + # @param raw_url [URI::Generic, ZyppUrl] Optional raw repository URL # @param product_dir [String] Product directory # @param enabled [Boolean] Is the repository enabled? # @param autorefresh [Boolean] Is auto-refresh enabled for this repository? @@ -138,8 +136,7 @@ @name = name @enabled = enabled @autorefresh = autorefresh - @url = url - @raw_url = raw_url || url + @raw_url = ZyppUrl.new(raw_url || url) @product_dir = product_dir end @@ -149,7 +146,7 @@ # # @return [Symbol,nil] URL scheme, nil if the URL is not defined def scheme - url.scheme ? url.scheme.to_sym : nil + raw_url&.scheme&.to_sym end # Return products contained in the repository @@ -174,7 +171,15 @@ # # @return [Boolean] true if the repository is considered local; false otherwise def local? - LOCAL_SCHEMES.include?(scheme) + raw_url.local? + end + + # Repository URL, expanded version (ie. with the repository variables already + # replaced by their values) + # + # @return [ZyppUrl] + def url + raw_url.expanded end # Determine if the repository is enabled @@ -251,20 +256,15 @@ # Change the repository URL # # The URL will be changed only in memory. Calling to - # Yast::Pkg.SourceSaveAll will make the removal persistent. - # - # @param new_url [String,URI] the new URL (with unexpanded variables, - # it sets the `raw_url` value, the `url` attribute will - # be evaluated automatically) + # Yast::Pkg.SourceSaveAll will make the change persistent. # - # @see Yast::Pkg.SourceDelete - # @see Yast::Pkg.SourceSaveAll - def url=(new_url) + # @param new_url [String,ZyppUrl] the new URL (with unexpanded variables) + def raw_url=(new_url) return unless Yast::Pkg.SourceChangeUrl(repo_id, new_url.to_s) - # its safe to call URI() on URI object - @raw_url = URI(new_url) - @url = URI(Yast::Pkg.ExpandedUrl(new_url.to_s)) + @raw_url = ZyppUrl.new(new_url) end + + alias_method :url=, :raw_url= end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-4.3.14/library/packages/src/lib/y2packager/zypp_url.rb new/yast2-4.3.15/library/packages/src/lib/y2packager/zypp_url.rb --- old/yast2-4.3.14/library/packages/src/lib/y2packager/zypp_url.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-4.3.15/library/packages/src/lib/y2packager/zypp_url.rb 2020-07-21 08:58:01.000000000 +0200 @@ -0,0 +1,180 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) 2020 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. +# ------------------------------------------------------------------------------ + +require "uri" +require "yast" +require "delegate" + +module Y2Packager + # This class represents a libzypp URL + # + # Libzypp URLs do not conform to rfc3986 because they can include the so-called + # Repository Variables. Those vars can have several formats like $variable, + # ${variable}, ${variable-word} or ${variable+word}. According to libzypp's + # documentation, the variables can appear in any component of the URL (host, path, + # port...) except in scheme, user or password. But, at the time of writing, zypper + # throws an "invalid port component" error when trying to use variables as part of + # the port, even with the most recent available version of libzypp. + # + # See https://doc.opensuse.org/projects/libzypp/HEAD/zypp-repovars.html + # + # The current implementation relies on SimpleDelegator to expose all the methods + # of an underlying URI object, so objects of this class can be used as a direct + # replacement in places that used to use URI, like {Y2Packager::Repository#raw_url} + # + class ZyppUrl < SimpleDelegator + Yast.import "Pkg" + include Yast::Logger + + # Repository schemes considered local (see #local?) + # https://github.com/openSUSE/libzypp/blob/a7a038aeda1ad6d9e441e7d3755612aa83320dce/zypp/Url.cc#L458 + LOCAL_SCHEMES = [:cd, :dvd, :dir, :hd, :iso, :file].freeze + + # Constructor + # + # If the argument is a string with an invalid URL, an empty URL is created + # + # @param url [String, ZyppUrl, URI::Generic] + def initialize(url) + uri = + begin + URI(repovars_escape(url.to_s)) + rescue URI::InvalidURIError => e + log.error "Failed to parse URL, considered as empty: #{e.inspect}" + URI("") + end + + __setobj__(uri) + end + + # @return [URI::Generic] + def uri + __getobj__ + end + + alias_method :to_uri, :uri + + # Constructs String from the URL + # + # @return [String] + def to_s + repovars_unescape(uri.to_s) + end + + # See URI::Generic#hostname + # + # @return [String] + def hostname + repovars_unescape(uri.hostname) + end + + # See URI::Generic#hostname + # + # FIXME: escaping does not work here because the port wouldn't accept the escaped + # characters either. If we really want to support the usage of repository variables + # in the port, we would likely have to implement one of these solutions: + # + # 1) Modify the regexp used by URI to parse/validate the port, so it accepts the + # vars (escaped or not). That's not as easy as the documentation of the URI class + # suggests and may affect the reliability of the parsing. + # 2) Extract the port section before parsing the URL if it contains repovars, storing + # its value in a separate instance variable and restoring it on demand. + # + # Anyways, using variables in the port of an URL doesn't seem to really work in libzypp, + # although it's documented to be valid. + # + # @return [String] + def port + repovars_unescape(uri.port) + end + + # See URI::Generic#path + # + # @return [String] + def path + repovars_unescape(uri.path) + end + + # See URI::Generic#path + # + # Offered for completeness, even if the query component makes very little + # sense in a zypper URL. + # + # @return [String] + def query + repovars_unescape(uri.query) + end + + # Whether the URL is local + # + # @return [Boolean] true if the URL is considered local; false otherwise + def local? + LOCAL_SCHEMES.include?(scheme&.to_sym) + end + + # Expanded version of the URL in which the repository vars has been replaced + # by their value + # + # @return [ZyppUrl] an URL that is expected to conform to rfc3986 + def expanded + ZyppUrl.new(Yast::Pkg.ExpandedUrl(to_s)) + end + + # String representation of the state of the object + # + # @return [String] + def inspect + # Prevent SimpleDelegator from forwarding this to the wrapped URI object + "#<#{self.class}:#{object_id}} @uri=#{uri.inspect}>" + end + + # Compares two URLs + # + # NOTE: this considers an URI::Generic object to be equal if it represents + # the same URL. That should increase a bit the robustness when a ZyppUrl + # object is introduced to replace an existing URI one. + def ==(other) + if other.is_a?(URI::Generic) + uri == other + elsif other.class == self.class + uri == other.uri + else + false + end + end + + # @see #== + alias_method :eql?, :== + + private + + # Preprocess a string so it can be accepted as a valid URI + # + # Escaping and unescaping the invalid characters is implemented as an + # alternative to the solution that may look more obvious and elegant: + # configuring the parser of URI to accept those characters. Done this way + # because configuring the parser implies dealing with very complex regexps, + # which is not only risky but would also prevent us from benefiting from + # future improvements in the Ruby's URI regexps. + # + # @param str [String] original string that may include repo vars + # @return [String] + def repovars_escape(str) + str.gsub("{", "%7B").gsub("}", "%7D") + end + + # @see #repovars_escape + def repovars_unescape(str) + str.gsub("%7B", "{").gsub("%7D", "}") + end + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-4.3.14/library/packages/test/repository_test.rb new/yast2-4.3.15/library/packages/test/repository_test.rb --- old/yast2-4.3.14/library/packages/test/repository_test.rb 2020-07-10 16:29:19.000000000 +0200 +++ new/yast2-4.3.15/library/packages/test/repository_test.rb 2020-07-21 08:58:01.000000000 +0200 @@ -12,6 +12,7 @@ let(:enabled) { true } let(:autorefresh) { true } let(:repo_url) { URI("http://download.opensuse.org/update/leap/42.1/oss") } + let(:repo_raw_url) { repo_url } subject(:repo) do Y2Packager::Repository.new(repo_id: repo_id, name: "repo-oss", enabled: enabled, @@ -88,17 +89,79 @@ context "when a valid repo_id is given" do let(:repo_data) do - { "enabled" => true, "autorefresh" => true, "url" => repo_url, "raw_url" => repo_url, + { "enabled" => true, "autorefresh" => true, "url" => repo_url, "raw_url" => repo_raw_url, "name" => "Repo #1", "product_dir" => "/product", "repo_alias" => "alias" } end - it "returns a repository with the given repo_id" do + it "returns the repository with the given repo_id" do repo = described_class.find(repo_id) expect(repo.repo_id).to eq(repo_id) expect(repo.enabled?).to eq(repo_data["enabled"]) expect(repo.url).to eq(URI(repo_data["url"])) expect(repo.product_dir).to eq("/product") end + + context "if the raw url contains a repo var like $releasever" do + let(:repo_raw_url) { "http://download.opensuse.org/update/leap/$releasever/oss" } + + it "returns the repository with the given repo_id" do + repo = described_class.find(repo_id) + expect(repo.repo_id).to eq(repo_id) + expect(repo.enabled?).to eq(repo_data["enabled"]) + expect(repo.raw_url.to_s).to eq(repo_data["raw_url"].to_s) + expect(repo.product_dir).to eq("/product") + end + end + + # Regression test for bug#1172867, using ${var_name} used to cause an exception + context "if the raw url contains a repo var like ${releasever}" do + let(:repo_raw_url) { "http://download.opensuse.org/update/leap/${releasever}/oss" } + + it "returns the repository with the given repo_id" do + repo = described_class.find(repo_id) + expect(repo.repo_id).to eq(repo_id) + expect(repo.enabled?).to eq(repo_data["enabled"]) + expect(repo.raw_url.to_s).to eq(repo_data["raw_url"].to_s) + expect(repo.product_dir).to eq("/product") + end + end + + # Regression test for bug#1172867, part 2 + context "if the raw url contains a repo var like ${var-word}" do + let(:repo_raw_url) { "http://download.opensuse.org/update/leap/${var-word}/oss" } + + it "returns the repository with the given repo_id" do + repo = described_class.find(repo_id) + expect(repo.repo_id).to eq(repo_id) + expect(repo.enabled?).to eq(repo_data["enabled"]) + expect(repo.raw_url.to_s).to eq(repo_data["raw_url"].to_s) + expect(repo.product_dir).to eq("/product") + end + end + + # Regression test for bug#1172867, part 3 + context "if the raw url contains a repo var like ${var+word}" do + let(:repo_raw_url) { "http://download.opensuse.org/update/leap/${var+word}/oss" } + + it "returns the repository with the given repo_id" do + repo = described_class.find(repo_id) + expect(repo.repo_id).to eq(repo_id) + expect(repo.enabled?).to eq(repo_data["enabled"]) + expect(repo.raw_url.to_s).to eq(repo_data["raw_url"].to_s) + expect(repo.product_dir).to eq("/product") + end + end + + context "if the raw url cannot be parsed" do + let(:repo_raw_url) { "http://download.opensuse.org:80$releasever/update/leap/15.2/oss" } + + it "returns a repository with an empty url" do + repo = described_class.find(repo_id) + expect(repo.repo_id).to eq(repo_id) + expect(repo.raw_url.to_s).to eq "" + expect(repo.url.to_s).to eq "" + end + end end context "when an invalid repo_id is given" do @@ -130,7 +193,7 @@ describe "#local" do before do - allow(repo).to receive(:scheme).and_return(scheme) + allow(repo.raw_url).to receive(:scheme).and_return(scheme) end context "when scheme is :cd" do @@ -283,6 +346,12 @@ it "allows using an URI class parameter" do new_url = URI("https://example.com/new_repo") expect(Yast::Pkg).to receive(:SourceChangeUrl).with(repo.repo_id, new_url.to_s).and_return(true) + expect { repo.url = new_url }.to change { repo.url.to_s }.from(repo.url.to_s).to(new_url.to_s) + end + + it "allows using an ZyppUrl class parameter" do + new_url = Y2Packager::ZyppUrl.new("https://example.com/new_repo") + expect(Yast::Pkg).to receive(:SourceChangeUrl).with(repo.repo_id, new_url.to_s).and_return(true) expect { repo.url = new_url }.to change { repo.url }.from(repo.url).to(new_url) end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-4.3.14/package/yast2.changes new/yast2-4.3.15/package/yast2.changes --- old/yast2-4.3.14/package/yast2.changes 2020-07-10 16:29:19.000000000 +0200 +++ new/yast2-4.3.15/package/yast2.changes 2020-07-21 08:58:01.000000000 +0200 @@ -1,4 +1,13 @@ ------------------------------------------------------------------- +Thu Jul 16 12:48:24 UTC 2020 - Ancor Gonzalez Sosa <[email protected]> + +- Better management of libzypp repovars (eg. those enclosed in + curly brackets) introducing the new Y2Packager::ZyppUrl class +- Do not crash during the upgrade process if some repository URL + cannot be parsed (bsc#1172867) +- 4.3.15 + +------------------------------------------------------------------- Fri Jul 10 14:15:30 UTC 2020 - David Diaz <[email protected]> - Make CFA::MultiFileConfig fully reusable (related to bsc#1155735, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-4.3.14/package/yast2.spec new/yast2-4.3.15/package/yast2.spec --- old/yast2-4.3.14/package/yast2.spec 2020-07-10 16:29:19.000000000 +0200 +++ new/yast2-4.3.15/package/yast2.spec 2020-07-21 08:58:01.000000000 +0200 @@ -17,7 +17,7 @@ Name: yast2 -Version: 4.3.14 +Version: 4.3.15 Release: 0 Summary: YaST2 Main Package License: GPL-2.0-only
