From 28c58818070944457f32511c8ae162faccba490c Mon Sep 17 00:00:00 2001 From: Steve Mokris Date: Sat, 2 Mar 2024 18:50:44 -0500 Subject: [PATCH] Support pip freeze URL format `pip freeze` (https://pip.pypa.io/en/stable/cli/pip_freeze/) "outputs installed packages in requirements format" (https://pip.pypa.io/en/stable/reference/requirement-specifiers/). As of pip 19.1, pip also supports specifying a requirement as a URL, and, for packages that were installed using URL format, `pip freeze` will output package requirements in URL format. However, Puppet's `pip freeze` parser doesn't support URL format, so it doesn't realize that a package is installed if it uses URL format, causing every `puppet agent` run to attempt to reinstall the package. This PR adds support for parsing `pip freeze` URL format. (cherry picked from commit 207a7dc7f271c9d97be400d0d2ebb80a5cda6cd2) --- lib/puppet/provider/package/pip.rb | 3 +++ spec/unit/provider/package/pip_spec.rb | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/lib/puppet/provider/package/pip.rb b/lib/puppet/provider/package/pip.rb index 7325cd6a6f6..07be06b36c5 100644 --- a/lib/puppet/provider/package/pip.rb +++ b/lib/puppet/provider/package/pip.rb @@ -99,9 +99,12 @@ def self.instances(target_command = nil) # Parse lines of output from `pip freeze`, which are structured as: # _package_==_version_ or _package_===_version_ + # or _package_ @ someURL@_version_ def self.parse(line) if line.chomp =~ /^([^=]+)===?([^=]+)$/ {:ensure => $2, :name => $1, :provider => name} + elsif line.chomp =~ /^([^@]+) @ [^@]+@(.+)$/ + { :ensure => Regexp.last_match(2), :name => Regexp.last_match(1), :provider => name } end end diff --git a/spec/unit/provider/package/pip_spec.rb b/spec/unit/provider/package/pip_spec.rb index c16c4953cac..6113c60d1e2 100644 --- a/spec/unit/provider/package/pip_spec.rb +++ b/spec/unit/provider/package/pip_spec.rb @@ -38,6 +38,14 @@ }) end + it "should correctly parse URL format" do + expect(described_class.parse("real_package @ git+https://github.com/example/test.git@6b4e203b66c1de7345984882e2b13bf87c700095")).to eq({ + :ensure => "6b4e203b66c1de7345984882e2b13bf87c700095", + :name => "real_package", + :provider => :pip, + }) + end + it "should return nil on invalid input" do expect(described_class.parse("foo")).to eq(nil) end