Your message dated Sun, 29 Jan 2023 23:36:40 +0000
with message-id <[email protected]>
and subject line Bug#988074: fixed in trocla 0.5.0-1
has caused the Debian Bug report #988074,
regarding trocla: diff for NMU version 0.3.0-0.1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
988074: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=988074
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: trocla
Version: 0.2.3-1
Severity: normal
Tags: patch  pending

Dear maintainer,

I've prepared an NMU for trocla (versioned as 0.3.0-0.1) and
uploaded it to DELAYED/10. Please feel free to tell me if I
should delay it longer.

I also uploaded it to experimental, given that we're in a freeze, as a
precaution, in case you want to just cherry-pick the two patches to just
fix the RC bugs. But considering that 0.2.3 is pretty broken, I suspect
that wouldn't be a good idea anyways.

Note that this diff includes a pile of changes that had accumulated in
the git repository on salsa and are therefore not only my changes. My
work may be more easily reviewed here:

https://salsa.debian.org/anarcat/trocla/-/commits/debian/experimental/

You can also see the pipeline has been fixed by those commits here:

https://salsa.debian.org/anarcat/trocla/-/pipelines/251950

Regards.
diff -Nru trocla-0.2.3/bin/trocla trocla-0.3.0/bin/trocla
--- trocla-0.2.3/bin/trocla	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/bin/trocla	2021-05-04 15:31:47.000000000 -0400
@@ -47,18 +47,20 @@
 end.parse!
 
 def create(options)
-  Trocla.new(options.delete(:config_file)).password(
+  [ Trocla.new(options.delete(:config_file)).password(
     options.delete(:trocla_key),
     options.delete(:trocla_format),
     options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
-  )
+  ) , 0 ]
 end
 
 def get(options)
-  Trocla.new(options.delete(:config_file)).get_password(
+  res = Trocla.new(options.delete(:config_file)).get_password(
     options.delete(:trocla_key),
-    options.delete(:trocla_format)
+    options.delete(:trocla_format),
+    options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
   )
+  [ res, res.nil? ? 1 : 0 ]
 end
 def set(options)
   if options.delete(:ask_password)
@@ -67,7 +69,7 @@
     pwd2 = ask('Repeat password: ') { |q| q.echo = 'x' }.to_s
     unless password == pwd2
       STDERR.puts 'Passwords did not match, exiting!'
-      exit 1
+      return [ nil, 1 ]
     end
   else
     password = options.delete(:password) || STDIN.read.chomp
@@ -78,29 +80,29 @@
   value = if no_format
     password
   else
-    trocla.formats(format).format(password, options.delete(:other_options).shift.to_s)
+    trocla.formats(format).format(password, (YAML.load(options.delete(:other_options).shift.to_s)||{}))
   end
   trocla.set_password(
     options.delete(:trocla_key),
     format,
     value
   )
-  ''
+  [ '', 0 ]
 end
 
 def reset(options)
-  Trocla.new(options.delete(:config_file)).reset_password(
+  [ Trocla.new(options.delete(:config_file)).reset_password(
     options.delete(:trocla_key),
     options.delete(:trocla_format),
     options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
-  )
+  ), 0 ]
 end
 
 def delete(options)
-  Trocla.new(options.delete(:config_file)).delete_password(
+  [ Trocla.new(options.delete(:config_file)).delete_password(
     options.delete(:trocla_key),
     options.delete(:trocla_format)
-  )
+  ), 0 ]
 end
 
 def formats(options)
@@ -125,7 +127,8 @@
     options[:other_options] = ARGV
     check_format(options[:trocla_format]) unless ['delete','formats'].include?(action)
     begin
-      if result = send(action,options)
+      result, excode = send(action,options)
+      if result
         puts result.is_a?(String) ? result : result.inspect
       end
     rescue Exception => e
@@ -136,6 +139,7 @@
       raise e if options[:trace]
       exit 1
     end
+    exit excode.nil? ? 0 : excode
 else
     STDERR.puts "Please supply one of the following actions: #{actions.join(', ')}"
     STDERR.puts "Use #{$0} --help to get a list of options for these actions"
diff -Nru trocla-0.2.3/CHANGELOG.md trocla-0.3.0/CHANGELOG.md
--- trocla-0.2.3/CHANGELOG.md	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/CHANGELOG.md	2021-05-04 15:31:47.000000000 -0400
@@ -1,5 +1,14 @@
 # Changelog
 
+## to 0.3.0
+
+* Add open method to be able to immediately close a trocla store after using it - thanks martinpfeiffer
+* Add typesafe charset - thanks hggh
+* Support cost option for bcrypt
+* address concurrency corner cases, when 2 concurrent threads or even processes
+  are currently calculating the same (expensive) format.
+* parse additional options on cli (#39 & #46) - thanks fe80
+
 ## to 0.2.3
 
 1. Add extended CA validity profiles
diff -Nru trocla-0.2.3/debian/changelog trocla-0.3.0/debian/changelog
--- trocla-0.2.3/debian/changelog	2016-03-01 16:05:19.000000000 -0500
+++ trocla-0.3.0/debian/changelog	2021-05-04 15:32:32.000000000 -0400
@@ -1,3 +1,39 @@
+trocla (0.3.0-0.1) experimental; urgency=medium
+
+  [ Antoine Beaupré ]
+  * Non-maintainer upload.
+  * New upstream release (Closes: #974697)
+  * Remove no-pending_for patch: dependency packaged in Debian and added
+    to Build-Depends.
+  * remove fix_version.patch: just ship the version instead of chasing the
+    version number in a patch (!?)
+  * disable the failing test, after discussion with upstream (Closes:
+    #982154)
+  * change section to admin (Closes: #832261)
+  * expand search path for sample config file to fix autopkgtest (Closes:
+    #830240)
+
+  [ Cédric Boutillier ]
+  * Bump debhelper compatibility level to 9
+  * Use https:// in Vcs-* fields
+  * Run wrap-and-sort on packaging files
+  * Use new default gem2deb Rakefile to run the tests
+
+  [ Utkarsh Gupta ]
+  * Add salsa-ci.yml
+
+  [ Debian Janitor ]
+  * Use secure copyright file specification URI.
+  * Use secure URI in debian/watch.
+  * Bump debhelper from deprecated 9 to 12.
+  * Set debhelper-compat version in Build-Depends.
+  * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository,
+    Repository-Browse.
+  * Update Vcs-* headers from URL redirect.
+  * Use canonical URL in Vcs-Git.
+
+ -- Antoine Beaupré <[email protected]>  Tue, 04 May 2021 15:32:32 -0400
+
 trocla (0.2.3-1) unstable; urgency=medium
 
   * Team upload.
diff -Nru trocla-0.2.3/debian/compat trocla-0.3.0/debian/compat
--- trocla-0.2.3/debian/compat	2016-03-01 16:05:19.000000000 -0500
+++ trocla-0.3.0/debian/compat	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-7
diff -Nru trocla-0.2.3/debian/control trocla-0.3.0/debian/control
--- trocla-0.2.3/debian/control	2016-03-01 16:05:19.000000000 -0500
+++ trocla-0.3.0/debian/control	2021-05-04 15:32:32.000000000 -0400
@@ -1,19 +1,20 @@
 Source: trocla
-Section: ruby
+Section: admin
 Priority: optional
-Maintainer: Debian Ruby Extras Maintainers <[email protected]>
+Maintainer: Debian Ruby Team <[email protected]>
 Uploaders: Jonas Genannt <[email protected]>
-Build-Depends: debhelper (>= 7.0.50~),
+Build-Depends: debhelper-compat (= 12),
                gem2deb,
                rake,
                ruby-bcrypt,
                ruby-highline,
+               ruby-mocha,
                ruby-moneta,
                ruby-rspec,
-               ruby-mocha
+               ruby-rspec-pending-for,
 Standards-Version: 3.9.7
-Vcs-Git: git://anonscm.debian.org/pkg-ruby-extras/trocla.git
-Vcs-Browser: https://anonscm.debian.org/cgit/pkg-ruby-extras/trocla.git
+Vcs-Git: https://salsa.debian.org/ruby-team/trocla.git
+Vcs-Browser: https://salsa.debian.org/ruby-team/trocla
 Homepage: https://github.com/duritong/trocla
 Testsuite: autopkgtest-pkg-ruby
 XS-Ruby-Versions: all
diff -Nru trocla-0.2.3/debian/copyright trocla-0.3.0/debian/copyright
--- trocla-0.2.3/debian/copyright	2016-03-01 16:05:19.000000000 -0500
+++ trocla-0.3.0/debian/copyright	2021-05-04 15:32:32.000000000 -0400
@@ -1,4 +1,4 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 Upstream-Name: trocla
 Source: https://github.com/duritong/trocla
 
diff -Nru trocla-0.2.3/debian/patches/830240.patch trocla-0.3.0/debian/patches/830240.patch
--- trocla-0.2.3/debian/patches/830240.patch	1969-12-31 19:00:00.000000000 -0500
+++ trocla-0.3.0/debian/patches/830240.patch	2021-05-04 15:32:32.000000000 -0400
@@ -0,0 +1,35 @@
+Description: load trocla from installed code
+ In autopkgtest, we fail to find the trocla config file because
+ "gem2deb-test-runner will remove lib directory from source tree
+ during tests", according to:
+ .
+ https://wiki.debian.org/Teams/Ruby/Packaging/Tests
+ .
+ The workaround is to find out where we loaded trocla from and use
+ *that* as a base directory.
+Author: Antoine Beaupré <[email protected]>
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=830240
+Origin: Debian
+Last-Update: 2021-05-04
+Forwarded: https://github.com/duritong/trocla/pull/64
+
+Index: b/spec/spec_helper.rb
+===================================================================
+--- a/spec/spec_helper.rb	2021-05-04 20:40:41.480961893 -0400
++++ b/spec/spec_helper.rb	2021-05-04 20:41:20.300799490 -0400
+@@ -225,7 +225,14 @@ RSpec.shared_examples 'store_validation'
+ end
+ 
+ def default_config
+-  @default_config ||= YAML.load(File.read(File.expand_path(base_dir+'/lib/trocla/default_config.yaml')))
++  config_path = false
++  for p in [
++          File.expand_path(base_dir+'/lib/trocla/default_config.yaml'),
++          File.expand_path(File.dirname($LOADED_FEATURES.grep(/trocla.rb/)[0])+'/trocla/default_config.yaml'),
++        ] do
++    config_path = p if File.exists?(p)
++  end
++  @default_config ||= YAML.load(File.read(config_path))
+ end
+ 
+ def test_config
diff -Nru trocla-0.2.3/debian/patches/fix_version.patch trocla-0.3.0/debian/patches/fix_version.patch
--- trocla-0.2.3/debian/patches/fix_version.patch	2016-03-01 16:05:19.000000000 -0500
+++ trocla-0.3.0/debian/patches/fix_version.patch	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-Description: do not ship VERSION file on top library level
-Author: Jonas Genannt <[email protected]>
-Forwared: not-needed
-
---- a/lib/trocla/version.rb
-+++ b/lib/trocla/version.rb
-@@ -2,16 +2,11 @@
- class Trocla
-   class VERSION
-     version = {}
--    File.read(File.join(File.dirname(__FILE__), '../', 'VERSION')).each_line do |line|
--      type, value = line.chomp.split(":")
--      next if type =~ /^\s+$/ || value =~ /^\s+$/
--      version[type] = value
--    end
-     
--    MAJOR = version['major']
--    MINOR = version['minor']
--    PATCH = version['patch']
--    BUILD = version['build']
-+    MAJOR = 0
-+    MINOR = 2
-+    PATCH = 3
-+    BUILD = ''
-     
-     STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
-     
diff -Nru trocla-0.2.3/debian/patches/no-pending_for trocla-0.3.0/debian/patches/no-pending_for
--- trocla-0.2.3/debian/patches/no-pending_for	2016-03-01 16:05:19.000000000 -0500
+++ trocla-0.3.0/debian/patches/no-pending_for	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-Index: trocla/spec/trocla/formats/x509_spec.rb
-===================================================================
---- trocla.orig/spec/trocla/formats/x509_spec.rb
-+++ trocla/spec/trocla/formats/x509_spec.rb
-@@ -184,18 +184,14 @@ describe "Trocla::Format::X509" do
-       ca2 = OpenSSL::X509::Certificate.new(ca2_str)
-       expect(ca2.issuer.to_s).to eq(@ca.subject.to_s)
-       expect((Date.parse(ca2.not_after.localtime.to_s) - Date.today).to_i).to eq(365)
--      pending_for(:engine => 'jruby',:reason => 'NameConstraints verification seem to be broken in jRuby: https://github.com/jruby/jruby/issues/3502') do
-         expect(verify(@ca,ca2)).to be true
--      end
- 
-       expect(ca2.extensions.find{|e| e.oid == 'basicConstraints' }.value).to eq('CA:TRUE')
-       ku = ca2.extensions.find{|e| e.oid == 'keyUsage' }.value
-       expect(ku).to match(/Certificate Sign/)
-       expect(ku).to match(/CRL Sign/)
-       nc = ca2.extensions.find{|e| e.oid == 'nameConstraints' }.value
--      pending_for(:engine => 'jruby',:reason => 'NameConstraints verification seem to be broken in jRuby: https://github.com/jruby/jruby/issues/3502') do
-         expect(nc).to match(/Permitted:\n  DNS:example.com\n  DNS:bla.example.net/)
--      end
-       valid_cert_str = @trocla.password('myvalidexamplecert','x509', {
-         'subject'  => '/C=ZZ/O=Trocla Inc./CN=foo.example.com/[email protected]',
-         'ca' => 'mycert_with_nc'
-@@ -224,9 +220,7 @@ describe "Trocla::Format::X509" do
-       ca2 = OpenSSL::X509::Certificate.new(ca2_str)
-       expect(ca2.issuer.to_s).to eq(@ca.subject.to_s)
-       expect((Date.parse(ca2.not_after.localtime.to_s) - Date.today).to_i).to eq(365)
--      pending_for(:engine => 'jruby',:reason => 'NameConstraints verification seem to be broken in jRuby: https://github.com/jruby/jruby/issues/3502') do
-         expect(verify(@ca,ca2)).to be true
--      end
- 
-       expect(ca2.extensions.find{|e| e.oid == 'basicConstraints' }.value).to eq('CA:TRUE')
-       ku = ca2.extensions.find{|e| e.oid == 'keyUsage' }.value
-@@ -245,9 +239,7 @@ describe "Trocla::Format::X509" do
-       if %x{openssl version} =~ /1\.0\.[2-9]/
-         expect(verify([@ca,ca2],valid_cert)).to be true
-       else
--        skip_for(:engine => 'ruby',:reason => 'NameConstraints verification is broken on older openssl versions https://rt.openssl.org/Ticket/Display.html?id=3562') do
-           expect(verify([@ca,ca2],valid_cert)).to be true
--        end
-       end
- 
-       false_cert_str = @trocla.password('myfalseexamplecert','x509', {
-@@ -277,9 +269,7 @@ describe "Trocla::Format::X509" do
-       cert2 = OpenSSL::X509::Certificate.new(cert2_str)
-       expect(cert2.issuer.to_s).to eq(ca2.subject.to_s)
-       expect((Date.parse(cert2.not_after.localtime.to_s) - Date.today).to_i).to eq(365)
--      skip_for(:engine => 'jruby',:reason => 'Chained CA validation seems to be broken on jruby atm.') do
-         expect(verify([@ca,ca2],cert2)).to be true
--      end
-     end
- 
-     it 'respects all options' do
-Index: trocla/spec/spec_helper.rb
-===================================================================
---- trocla.orig/spec/spec_helper.rb
-+++ trocla/spec/spec_helper.rb
-@@ -1,7 +1,6 @@
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
- $LOAD_PATH.unshift(File.dirname(__FILE__))
- require 'rspec'
--require 'rspec/pending_for'
- require 'yaml'
- require 'trocla'
- 
diff -Nru trocla-0.2.3/debian/patches/series trocla-0.3.0/debian/patches/series
--- trocla-0.2.3/debian/patches/series	2016-03-01 16:05:19.000000000 -0500
+++ trocla-0.3.0/debian/patches/series	2021-05-04 15:32:32.000000000 -0400
@@ -1,2 +1,2 @@
-fix_version.patch
-no-pending_for
+830240.patch
+skip-test-982154-2e8082c.patch
diff -Nru trocla-0.2.3/debian/patches/skip-test-982154-2e8082c.patch trocla-0.3.0/debian/patches/skip-test-982154-2e8082c.patch
--- trocla-0.2.3/debian/patches/skip-test-982154-2e8082c.patch	1969-12-31 19:00:00.000000000 -0500
+++ trocla-0.3.0/debian/patches/skip-test-982154-2e8082c.patch	2021-05-04 15:32:32.000000000 -0400
@@ -0,0 +1,38 @@
+Description: OpenSSL 1.1.1h changed the way self-signed certs work
+ It is not clear yet why, but this started failing in
+ bullseye. Upstream recommends skipping the test until the figure out
+ the problem.
+Origin: upstream
+Bug: https://github.com/duritong/trocla/issues/63
+Bug-Debian: https://bugs.debian.org/982154
+Last-Update: 2021-05-04
+
+From 2e8082c994a245cc27c8ed1b60d76adcb4f5a679 Mon Sep 17 00:00:00 2001
+From: mh <[email protected]>
+Date: Wed, 5 May 2021 00:18:24 +0200
+Subject: [PATCH] fix #63 - skip self-signed cert verification until openssl
+ behavior change has been clarified
+
+---
+ spec/trocla/formats/x509_spec.rb | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/spec/trocla/formats/x509_spec.rb b/spec/trocla/formats/x509_spec.rb
+index 299f807..a3309d4 100644
+--- a/spec/trocla/formats/x509_spec.rb
++++ b/spec/trocla/formats/x509_spec.rb
+@@ -44,7 +44,13 @@ def verify(ca,cert)
+       expect(cert.public_key.n.num_bytes * 8).to eq(4096)
+       expect((Date.parse(cert.not_after.localtime.to_s) - Date.today).to_i).to eq(365)
+       # it's a self signed cert and NOT a CA
+-      expect(verify(cert,cert)).to be false
++      if Gem::Version.new(%x{openssl version}.split(' ')[1]) > Gem::Version.new('1.1.1g')
++        skip_for(:engine => 'ruby',:reason => 'Requires clarification in behavior change on openssl side: https://github.com/openssl/openssl/issues/15146') do
++          expect(verify(cert,cert)).to be false
++        end
++      else
++        expect(verify(cert,cert)).to be false
++      end
+ 
+       v = cert.extensions.find{|e| e.oid == 'basicConstraints' }.value
+       expect(v).to eq('CA:FALSE')
diff -Nru trocla-0.2.3/debian/ruby-tests.rake trocla-0.3.0/debian/ruby-tests.rake
--- trocla-0.2.3/debian/ruby-tests.rake	2016-03-01 16:05:19.000000000 -0500
+++ trocla-0.3.0/debian/ruby-tests.rake	2021-05-04 15:32:32.000000000 -0400
@@ -1,7 +1,5 @@
-require 'rspec/core/rake_task'
+require 'gem2deb/rake/spectask'
 
-RSpec::Core::RakeTask.new(:spec) do |spec|
+Gem2Deb::Rake::RSpecTask.new do |spec|
   spec.pattern = './spec/**/*_spec.rb'
 end
-
-task :default => :spec
diff -Nru trocla-0.2.3/debian/rules trocla-0.3.0/debian/rules
--- trocla-0.2.3/debian/rules	2016-03-01 16:05:19.000000000 -0500
+++ trocla-0.3.0/debian/rules	2021-05-04 15:32:32.000000000 -0400
@@ -16,7 +16,3 @@
 
 %:
 	dh $@ --buildsystem=ruby --with ruby
-
-override_dh_auto_install:
-	dh_auto_install
-	rm debian/trocla/usr/lib/ruby/vendor_ruby/VERSION
diff -Nru trocla-0.2.3/debian/upstream/metadata trocla-0.3.0/debian/upstream/metadata
--- trocla-0.2.3/debian/upstream/metadata	1969-12-31 19:00:00.000000000 -0500
+++ trocla-0.3.0/debian/upstream/metadata	2021-05-04 15:32:32.000000000 -0400
@@ -0,0 +1,4 @@
+Bug-Database: https://github.com/duritong/trocla/issues
+Bug-Submit: https://github.com/duritong/trocla/issues/new
+Repository: https://github.com/duritong/trocla.git
+Repository-Browse: https://github.com/duritong/trocla
diff -Nru trocla-0.2.3/debian/watch trocla-0.3.0/debian/watch
--- trocla-0.2.3/debian/watch	2016-03-01 16:05:19.000000000 -0500
+++ trocla-0.3.0/debian/watch	2021-05-04 15:32:32.000000000 -0400
@@ -1,2 +1,2 @@
 version=3
-http://pkg-ruby-extras.alioth.debian.org/cgi-bin/gemwatch/trocla .*/trocla-(.*).tar.gz
+https://pkg-ruby-extras.alioth.debian.org/cgi-bin/gemwatch/trocla .*/trocla-(.*).tar.gz
diff -Nru trocla-0.2.3/ext/redhat/rubygem-trocla.spec trocla-0.3.0/ext/redhat/rubygem-trocla.spec
--- trocla-0.2.3/ext/redhat/rubygem-trocla.spec	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/ext/redhat/rubygem-trocla.spec	2021-05-04 15:31:47.000000000 -0400
@@ -2,7 +2,7 @@
 %global gem_name trocla
 
 Name: rubygem-%{gem_name}
-Version: 0.2.2
+Version: 0.3.0
 Release: 1%{?dist}
 Summary: Trocla a simple password generator and storage
 Group: Development/Languages
@@ -74,9 +74,11 @@
 
 cat <<EOF > %{buildroot}/%{_sysconfdir}/%{gem_name}rc.yaml
 ---
-adapter: :YAML
-adapter_options:
-      :file: '%{_sharedstatedir}/%{gem_name}/%{gem_name}_data.yaml'
+store: :moneta
+store_options:
+  adapter: :YAML
+  adapter_options:
+    :file: '%{_sharedstatedir}/%{gem_name}/%{gem_name}_data.yaml'
 EOF
 
 # Run the test suite
diff -Nru trocla-0.2.3/Gemfile trocla-0.3.0/Gemfile
--- trocla-0.2.3/Gemfile	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/Gemfile	2021-05-04 15:31:47.000000000 -0400
@@ -3,12 +3,22 @@
 # Example:
 #   gem "activesupport", ">= 2.3.5"
 
+if RUBY_VERSION.to_f <= 2.2
+  gem 'rack', '< 2.0'
+end
+
+if RUBY_VERSION.to_f < 2.1
+  gem 'nokogiri', '< 1.7'
+end
+
 if RUBY_VERSION.to_f > 1.8
   gem "moneta"
   gem "highline"
 else
   gem "moneta", "~> 0.7.20"
   gem "highline", "~> 1.6.2"
+  gem 'rake', '< 11'
+  gem 'git', '< 1.3'
 end
 
 if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'jruby')
@@ -22,7 +32,14 @@
   if RUBY_VERSION.to_f > 1.8
     gem "rspec"
     gem "rdoc"
-    gem "jeweler"
+    if RUBY_VERSION.to_f < 2.2
+      gem 'jeweler', '< 2.2'
+    else
+      gem "jeweler"
+    end
+    if RUBY_VERSION.to_f < 2.0
+      gem 'public_suffix', '~> 1.4.6'
+    end
   else
     gem "rspec", "~> 2.4"
     gem "rdoc", "~> 3.8"
diff -Nru trocla-0.2.3/lib/trocla/formats/bcrypt.rb trocla-0.3.0/lib/trocla/formats/bcrypt.rb
--- trocla-0.2.3/lib/trocla/formats/bcrypt.rb	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/lib/trocla/formats/bcrypt.rb	2021-05-04 15:31:47.000000000 -0400
@@ -1,6 +1,7 @@
 class Trocla::Formats::Bcrypt < Trocla::Formats::Base
+  expensive true
   require 'bcrypt'
   def format(plain_password,options={})
-    BCrypt::Password.create(plain_password).to_s
+    BCrypt::Password.create(plain_password, :cost => options['cost']||BCrypt::Engine.cost).to_s
   end
 end
diff -Nru trocla-0.2.3/lib/trocla/formats/x509.rb trocla-0.3.0/lib/trocla/formats/x509.rb
--- trocla-0.2.3/lib/trocla/formats/x509.rb	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/lib/trocla/formats/x509.rb	2021-05-04 15:31:47.000000000 -0400
@@ -1,5 +1,6 @@
 require 'openssl'
 class Trocla::Formats::X509 < Trocla::Formats::Base
+  expensive true
   def format(plain_password,options={})
 
     if plain_password.match(/-----BEGIN RSA PRIVATE KEY-----.*-----END RSA PRIVATE KEY-----.*-----BEGIN CERTIFICATE-----.*-----END CERTIFICATE-----/m)
diff -Nru trocla-0.2.3/lib/trocla/formats.rb trocla-0.3.0/lib/trocla/formats.rb
--- trocla-0.2.3/lib/trocla/formats.rb	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/lib/trocla/formats.rb	2021-05-04 15:31:47.000000000 -0400
@@ -8,6 +8,17 @@
     def render(output,render_options={})
       output
     end
+    def expensive?
+      self.class.expensive?
+    end
+    class << self
+      def expensive(is_expensive)
+        @expensive = is_expensive
+      end
+      def expensive?
+        @expensive == true
+      end
+    end
   end
 
   class << self
diff -Nru trocla-0.2.3/lib/trocla/store.rb trocla-0.3.0/lib/trocla/store.rb
--- trocla-0.2.3/lib/trocla/store.rb	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/lib/trocla/store.rb	2021-05-04 15:31:47.000000000 -0400
@@ -6,6 +6,12 @@
     @trocla = trocla
   end
 
+  # closes the store
+  # when called do whatever "closes" your
+  # store, e.g. close database connections.
+  def close
+  end
+
   # should return value for key & format
   # returns nil if nothing or a nil value
   # was found.
diff -Nru trocla-0.2.3/lib/trocla/stores/moneta.rb trocla-0.3.0/lib/trocla/stores/moneta.rb
--- trocla-0.2.3/lib/trocla/stores/moneta.rb	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/lib/trocla/stores/moneta.rb	2021-05-04 15:31:47.000000000 -0400
@@ -10,6 +10,10 @@
     @moneta = Moneta.new(store_config['adapter'],adapter_options)
   end
 
+  def close
+    moneta.close
+  end
+
   def get(key,format)
     moneta.fetch(key, {})[format]
   end
diff -Nru trocla-0.2.3/lib/trocla/util.rb trocla-0.3.0/lib/trocla/util.rb
--- trocla-0.2.3/lib/trocla/util.rb	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/lib/trocla/util.rb	2021-05-04 15:31:47.000000000 -0400
@@ -24,6 +24,7 @@
             'numeric'      => numeric,
             'hexadecimal'  => hexadecimal,
             'consolesafe'  => consolesafe,
+            'typesafe'     => typesafe,
           }
           h.each { |k, v| h[k] = v.uniq }
         end
@@ -50,6 +51,9 @@
       def numeric
         @numeric ||= ('0'..'9').to_a
       end
+      def typesafe
+        @typesafe ||= ('a'..'x').to_a - ['i'] - ['l'] + ('A'..'X').to_a - ['I'] - ['L'] + ('1'..'9').to_a
+      end
       def special_chars
         @special_chars ||= "*()&![]{}-".split(//)
       end
diff -Nru trocla-0.2.3/lib/trocla.rb trocla-0.3.0/lib/trocla.rb
--- trocla-0.2.3/lib/trocla.rb	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/lib/trocla.rb	2021-05-04 15:31:47.000000000 -0400
@@ -13,6 +13,17 @@
     end
   end
 
+  def self.open(config_file=nil)
+    trocla = Trocla.new(config_file)
+
+    if block_given?
+      yield trocla
+      trocla.close
+    else
+      trocla
+    end
+  end
+
   def password(key,format,options={})
     # respect a default profile, but let the
     # profiles win over the default options
@@ -35,10 +46,15 @@
     elsif !options['random'] && plain_pwd.nil?
       raise "Password must be present as plaintext if you don't want a random password"
     end
-    set_password(key,
-      format,
-      self.formats(format).format(plain_pwd,options),
-      options)
+    pwd = self.formats(format).format(plain_pwd,options)
+    # it's possible that meanwhile another thread/process was faster in
+    # formating the password. But we want todo that second lookup
+    # only for expensive formats
+    if self.formats(format).expensive?
+      get_password(key,format,options) || set_password(key, format, pwd, options)
+    else
+      set_password(key, format, pwd, options)
+    end
   end
 
   def get_password(key, format, options={})
@@ -78,6 +94,10 @@
     @config ||= read_config
   end
 
+  def close
+    store.close
+  end
+
   private
   def store
     @store ||= build_store
diff -Nru trocla-0.2.3/lib/VERSION trocla-0.3.0/lib/VERSION
--- trocla-0.2.3/lib/VERSION	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/lib/VERSION	2021-05-04 15:31:47.000000000 -0400
@@ -1,4 +1,4 @@
 major:0
-minor:2
-patch:3
+minor:3
+patch:0
 build:
diff -Nru trocla-0.2.3/metadata.yml trocla-0.3.0/metadata.yml
--- trocla-0.2.3/metadata.yml	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/metadata.yml	1969-12-31 19:00:00.000000000 -0500
@@ -1,188 +0,0 @@
---- !ruby/object:Gem::Specification
-name: trocla
-version: !ruby/object:Gem::Version
-  version: 0.2.3
-platform: ruby
-authors:
-- mh
-autorequire: 
-bindir: bin
-cert_chain: []
-date: 2016-02-15 00:00:00.000000000 Z
-dependencies:
-- !ruby/object:Gem::Dependency
-  name: moneta
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :runtime
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: highline
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :runtime
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: bcrypt
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :runtime
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: rspec
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: rdoc
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: jeweler
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: rspec-pending_for
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-description: Trocla helps you to generate random passwords and to store them in various
-  formats (plain, MD5, bcrypt) for later retrival.
-email: [email protected]
-executables:
-- trocla
-extensions: []
-extra_rdoc_files:
-- LICENSE.txt
-- README.md
-files:
-- ".document"
-- ".rspec"
-- ".travis.yml"
-- CHANGELOG.md
-- Gemfile
-- LICENSE.txt
-- README.md
-- Rakefile
-- bin/trocla
-- ext/redhat/rubygem-trocla.spec
-- lib/VERSION
-- lib/trocla.rb
-- lib/trocla/default_config.yaml
-- lib/trocla/encryptions.rb
-- lib/trocla/encryptions/none.rb
-- lib/trocla/encryptions/ssl.rb
-- lib/trocla/formats.rb
-- lib/trocla/formats/bcrypt.rb
-- lib/trocla/formats/md5crypt.rb
-- lib/trocla/formats/mysql.rb
-- lib/trocla/formats/pgsql.rb
-- lib/trocla/formats/plain.rb
-- lib/trocla/formats/sha1.rb
-- lib/trocla/formats/sha256crypt.rb
-- lib/trocla/formats/sha512crypt.rb
-- lib/trocla/formats/ssha.rb
-- lib/trocla/formats/x509.rb
-- lib/trocla/store.rb
-- lib/trocla/stores.rb
-- lib/trocla/stores/memory.rb
-- lib/trocla/stores/moneta.rb
-- lib/trocla/util.rb
-- lib/trocla/version.rb
-- spec/data/.keep
-- spec/spec_helper.rb
-- spec/trocla/encryptions/none_spec.rb
-- spec/trocla/encryptions/ssl_spec.rb
-- spec/trocla/formats/x509_spec.rb
-- spec/trocla/store/memory_spec.rb
-- spec/trocla/store/moneta_spec.rb
-- spec/trocla/util_spec.rb
-- spec/trocla_spec.rb
-- trocla.gemspec
-homepage: https://tech.immerda.ch/2011/12/trocla-get-hashed-passwords-out-of-puppet-manifests/
-licenses:
-- GPLv3
-metadata: {}
-post_install_message: 
-rdoc_options: []
-require_paths:
-- lib
-required_ruby_version: !ruby/object:Gem::Requirement
-  requirements:
-  - - ">="
-    - !ruby/object:Gem::Version
-      version: '0'
-required_rubygems_version: !ruby/object:Gem::Requirement
-  requirements:
-  - - ">="
-    - !ruby/object:Gem::Version
-      version: '0'
-requirements: []
-rubyforge_project: 
-rubygems_version: 2.2.2
-signing_key: 
-specification_version: 4
-summary: Trocla a simple password generator and storage
-test_files: []
diff -Nru trocla-0.2.3/README.md trocla-0.3.0/README.md
--- trocla-0.2.3/README.md	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/README.md	2021-05-04 15:31:47.000000000 -0400
@@ -168,6 +168,11 @@
 Password hashes for PostgreSQL servers. Requires the option `username` to be set
 to the username to which the password will be assigned.
 
+### bcrypt
+
+You are able to tune the [cost factor of bcrypt](https://github.com/codahale/bcrypt-ruby#cost-factors) by passing the option `cost`.
+Note: ruby bcrypt does not support a [cost > 31](https://github.com/codahale/bcrypt-ruby/blob/master/lib/bcrypt/password.rb#L45).
+
 ### x509
 
 This format takes a set of additional options. Required are:
diff -Nru trocla-0.2.3/spec/spec_helper.rb trocla-0.3.0/spec/spec_helper.rb
--- trocla-0.2.3/spec/spec_helper.rb	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/spec/spec_helper.rb	2021-05-04 15:31:47.000000000 -0400
@@ -282,3 +282,9 @@
 def remove_yaml_store
   File.unlink(trocla_yaml_file)
 end
+class Trocla::Formats::Sleep < Trocla::Formats::Base
+  def format(plain_password,options={})
+    sleep options['sleep'] ||= 0
+    (options['sleep'] + 1 ).times.collect{ plain_password }.join(' ')
+  end
+end
diff -Nru trocla-0.2.3/spec/trocla/formats/x509_spec.rb trocla-0.3.0/spec/trocla/formats/x509_spec.rb
--- trocla-0.2.3/spec/trocla/formats/x509_spec.rb	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/spec/trocla/formats/x509_spec.rb	2021-05-04 15:31:47.000000000 -0400
@@ -242,12 +242,12 @@
       expect(valid_cert.issuer.to_s).to eq(ca2.subject.to_s)
       expect((Date.parse(valid_cert.not_after.localtime.to_s) - Date.today).to_i).to eq(365)
       # workaround broken openssl
-      if %x{openssl version} =~ /1\.0\.[2-9]/
-        expect(verify([@ca,ca2],valid_cert)).to be true
-      else
+      if Gem::Version.new(%x{openssl version}.split(' ')[1]) < Gem::Version.new('1.0.2')
         skip_for(:engine => 'ruby',:reason => 'NameConstraints verification is broken on older openssl versions https://rt.openssl.org/Ticket/Display.html?id=3562') do
           expect(verify([@ca,ca2],valid_cert)).to be true
         end
+      else
+        expect(verify([@ca,ca2],valid_cert)).to be true
       end
 
       false_cert_str = @trocla.password('myfalseexamplecert','x509', {
@@ -311,7 +311,9 @@
       # https://stackoverflow.com/questions/13747212/determine-key-size-from-public-key-pem-format
       expect(cert.public_key.n.num_bytes * 8).to eq(2048)
       expect(verify(@ca,cert)).to be true
-      expect(cert.extensions.find{|e| e.oid == 'subjectAltName' }.value).to eq('DNS:www.test, DNS:test, DNS:test1, DNS:test2, DNS:test3')
+      skip_for(:engine => 'jruby',:reason => 'subjectAltName represenation is broken in jruby-openssl -> https://github.com/jruby/jruby-openssl/pull/123') do
+        expect(cert.extensions.find{|e| e.oid == 'subjectAltName' }.value).to eq('DNS:www.test, DNS:test, DNS:test1, DNS:test2, DNS:test3')
+      end
 
       expect(cert.extensions.find{|e| e.oid == 'basicConstraints' }.value).to eq('CA:FALSE')
       ku = cert.extensions.find{|e| e.oid == 'keyUsage' }.value
diff -Nru trocla-0.2.3/spec/trocla/util_spec.rb trocla-0.3.0/spec/trocla/util_spec.rb
--- trocla-0.2.3/spec/trocla/util_spec.rb	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/spec/trocla/util_spec.rb	2021-05-04 15:31:47.000000000 -0400
@@ -36,6 +36,14 @@
     end
   end
 
+  describe :typesafe_generator do
+    10.times.each do |i|
+      it "creates random typesafe password #{i}" do
+        expect(Trocla::Util.random_str(12, 'typesafe')).to match(/^[1-9a-hj-km-xA-HJ-KM-X]{12}$/)
+      end
+    end
+  end
+
   describe :salt do
     10.times.each do |i|
       it "contains only characters and numbers #{i}" do
diff -Nru trocla-0.2.3/spec/trocla_spec.rb trocla-0.3.0/spec/trocla_spec.rb
--- trocla-0.2.3/spec/trocla_spec.rb	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/spec/trocla_spec.rb	2021-05-04 15:31:47.000000000 -0400
@@ -4,144 +4,231 @@
 
   before(:each) do
     expect_any_instance_of(Trocla).to receive(:read_config).and_return(test_config)
-    @trocla = Trocla.new
   end
-
-  describe "password" do
-    it "generates random passwords by default" do
-      expect(@trocla.password('random1','plain')).not_to eq(@trocla.password('random2','plain'))
+  context 'in normal usage with' do
+    before(:each) do
+      @trocla = Trocla.new
+      @trocla.password('init','plain')
     end
 
-    it "generates passwords of length #{default_config['options']['length']}" do
-      expect(@trocla.password('random1','plain').length).to eq(default_config['options']['length'])
-    end
+    describe "password" do
+      it "generates random passwords by default" do
+        expect(@trocla.password('random1','plain')).not_to eq(@trocla.password('random2','plain'))
+      end
+
+      it "generates passwords of length #{default_config['options']['length']}" do
+        expect(@trocla.password('random1','plain').length).to eq(default_config['options']['length'])
+      end
+
+      Trocla::Formats.all.each do |format|
+        describe "#{format} password format" do
+          it "retursn a password hashed in the #{format} format" do
+            expect(@trocla.password('some_test',format,format_options[format])).not_to be_empty
+          end
 
-    Trocla::Formats.all.each do |format|
-      describe "#{format} password format" do
-        it "retursn a password hashed in the #{format} format" do
-          expect(@trocla.password('some_test',format,format_options[format])).not_to be_empty
+          it "returns the same hashed for the #{format} format on multiple invocations" do
+            expect([email protected]('some_test',format,format_options[format])).not_to be_empty
+            expect(@trocla.password('some_test',format,format_options[format])).to eq(round1)
+          end
+
+          it "also stores the plain password by default" do
+            pwd = @trocla.password('some_test','plain')
+            expect(pwd).not_to be_empty
+            expect(pwd.length).to eq(16)
+          end
+        end
+      end
+
+      Trocla::Formats.all.reject{|f| f == 'plain' }.each do |format|
+        it "raises an exception if not a random password is asked but plain password is not present for format #{format}" do
+          expect{@trocla.password('not_random',format, 'random' => false)}.to raise_error(/Password must be present as plaintext/)
         end
+      end
 
-        it "returns the same hashed for the #{format} format on multiple invocations" do
-          expect([email protected]('some_test',format,format_options[format])).not_to be_empty
-          expect(@trocla.password('some_test',format,format_options[format])).to eq(round1)
+      describe 'with profiles' do
+        it 'raises an exception on unknown profile' do
+          expect{@trocla.password('no profile known','plain',
+            'profiles' => 'unknown_profile') }.to raise_error(/No such profile unknown_profile defined/)
         end
 
-        it "also stores the plain password by default" do
-          pwd = @trocla.password('some_test','plain')
+        it 'takes a profile and merge its options' do
+          pwd = @trocla.password('some_test','plain', 'profiles' => 'rootpw')
+          expect(pwd).not_to be_empty
+          expect(pwd.length).to eq(32)
+          expect(pwd).to_not match(/[={}\[\]\?%\*()&!]+/)
+        end
+
+        it 'is possible to combine profiles but first profile wins' do
+          pwd = @trocla.password('some_test1','plain', 'profiles' => ['rootpw','login'])
+          expect(pwd).not_to be_empty
+          expect(pwd.length).to eq(32)
+          expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
+        end
+        it 'is possible to combine profiles but first profile wins 2' do
+          pwd = @trocla.password('some_test2','plain', 'profiles' => ['login','mysql'])
           expect(pwd).not_to be_empty
           expect(pwd.length).to eq(16)
+          expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
+        end
+        it 'is possible to combine profiles but first profile wins 3' do
+          pwd = @trocla.password('some_test3','plain', 'profiles' => ['mysql','login'])
+          expect(pwd).not_to be_empty
+          expect(pwd.length).to eq(32)
+          expect(pwd).to match(/[+%\/@=\?_.,:]+/)
         end
       end
     end
 
-    Trocla::Formats.all.reject{|f| f == 'plain' }.each do |format|
-      it "raises an exception if not a random password is asked but plain password is not present for format #{format}" do
-        expect{@trocla.password('not_random',format, 'random' => false)}.to raise_error(/Password must be present as plaintext/)
-      end
-    end
+    describe "set_password" do
+      it "resets hashed passwords on a new plain password" do
+        expect(@trocla.password('set_test','mysql')).not_to be_empty
+        expect(@trocla.get_password('set_test','mysql')).not_to be_nil
+        expect([email protected]('set_test','mysql')).not_to be_empty
 
-    describe 'with profiles' do
-      it 'raises an exception on unknown profile' do
-        expect{@trocla.password('no profile known','plain',
-          'profiles' => 'unknown_profile') }.to raise_error(/No such profile unknown_profile defined/)
-      end
-
-      it 'takes a profile and merge its options' do
-        pwd = @trocla.password('some_test','plain', 'profiles' => 'rootpw')
-        expect(pwd).not_to be_empty
-        expect(pwd.length).to eq(32)
-        expect(pwd).to_not match(/[={}\[\]\?%\*()&!]+/)
-      end
-
-      it 'is possible to combine profiles but first profile wins' do
-        pwd = @trocla.password('some_test','plain', 'profiles' => ['rootpw','login'])
-        expect(pwd).not_to be_empty
-        expect(pwd.length).to eq(32)
-        expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
-      end
-      it 'is possible to combine profiles but first profile wins 2' do
-        pwd = @trocla.password('some_test','plain', 'profiles' => ['login','mysql'])
-        expect(pwd).not_to be_empty
-        expect(pwd.length).to eq(16)
-        expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
-      end
-      it 'is possible to combine profiles but first profile wins 3' do
-        pwd = @trocla.password('some_test','plain', 'profiles' => ['mysql','login'])
-        expect(pwd).not_to be_empty
-        expect(pwd.length).to eq(32)
-        expect(pwd).to match(/[+%\/@=\?_.,:]+/)
+        expect(@trocla.set_password('set_test','plain','foobar')).not_to eq(old_plain)
+        expect(@trocla.get_password('set_test','mysql')).to be_nil
       end
-    end
-  end
 
-  describe "set_password" do
-    it "resets hashed passwords on a new plain password" do
-      expect(@trocla.password('set_test','mysql')).not_to be_empty
-      expect(@trocla.get_password('set_test','mysql')).not_to be_nil
-      expect([email protected]('set_test','mysql')).not_to be_empty
-
-      expect(@trocla.set_password('set_test','plain','foobar')).not_to eq(old_plain)
-      expect(@trocla.get_password('set_test','mysql')).to be_nil
-    end
-
-    it "otherwise updates only the hash" do
-      expect(mysql = @trocla.password('set_test2','mysql')).not_to be_empty
-      expect(md5crypt = @trocla.password('set_test2','md5crypt')).not_to be_empty
-      expect(plain = @trocla.get_password('set_test2','plain')).not_to be_empty
-
-      expect(new_mysql = @trocla.set_password('set_test2','mysql','foo')).not_to eql(mysql)
-      expect(@trocla.get_password('set_test2','mysql')).to eq(new_mysql)
-      expect(@trocla.get_password('set_test2','md5crypt')).to eq(md5crypt)
-      expect(@trocla.get_password('set_test2','plain')).to eq(plain)
+      it "otherwise updates only the hash" do
+        expect(mysql = @trocla.password('set_test2','mysql')).not_to be_empty
+        expect(md5crypt = @trocla.password('set_test2','md5crypt')).not_to be_empty
+        expect(plain = @trocla.get_password('set_test2','plain')).not_to be_empty
+
+        expect(new_mysql = @trocla.set_password('set_test2','mysql','foo')).not_to eql(mysql)
+        expect(@trocla.get_password('set_test2','mysql')).to eq(new_mysql)
+        expect(@trocla.get_password('set_test2','md5crypt')).to eq(md5crypt)
+        expect(@trocla.get_password('set_test2','plain')).to eq(plain)
+      end
     end
-  end
 
-  describe "reset_password" do
-    it "resets a password" do
-      plain1 = @trocla.password('reset_pwd','plain')
-      plain2 = @trocla.reset_password('reset_pwd','plain')
+    describe "reset_password" do
+      it "resets a password" do
+        plain1 = @trocla.password('reset_pwd','plain')
+        plain2 = @trocla.reset_password('reset_pwd','plain')
 
-      expect(plain1).not_to eq(plain2)
-    end
+        expect(plain1).not_to eq(plain2)
+      end
 
-    it "does not reset other formats" do
-      expect(mysql = @trocla.password('reset_pwd2','mysql')).not_to be_empty
-      expect(md5crypt1 = @trocla.password('reset_pwd2','md5crypt')).not_to be_empty
+      it "does not reset other formats" do
+        expect(mysql = @trocla.password('reset_pwd2','mysql')).not_to be_empty
+        expect(md5crypt1 = @trocla.password('reset_pwd2','md5crypt')).not_to be_empty
 
-      expect(md5crypt2 = @trocla.reset_password('reset_pwd2','md5crypt')).not_to be_empty
-      expect(md5crypt2).not_to eq(md5crypt1)
+        expect(md5crypt2 = @trocla.reset_password('reset_pwd2','md5crypt')).not_to be_empty
+        expect(md5crypt2).not_to eq(md5crypt1)
 
-      expect(@trocla.get_password('reset_pwd2','mysql')).to eq(mysql)
+        expect(@trocla.get_password('reset_pwd2','mysql')).to eq(mysql)
+      end
     end
-  end
 
-  describe "delete_password" do
-    it "deletes all passwords if no format is given" do
-      expect(@trocla.password('delete_test1','mysql')).not_to be_nil
-      expect(@trocla.get_password('delete_test1','plain')).not_to be_nil
+    describe "delete_password" do
+      it "deletes all passwords if no format is given" do
+        expect(@trocla.password('delete_test1','mysql')).not_to be_nil
+        expect(@trocla.get_password('delete_test1','plain')).not_to be_nil
 
-      @trocla.delete_password('delete_test1')
-      expect(@trocla.get_password('delete_test1','plain')).to be_nil
-      expect(@trocla.get_password('delete_test1','mysql')).to be_nil
-    end
+        @trocla.delete_password('delete_test1')
+        expect(@trocla.get_password('delete_test1','plain')).to be_nil
+        expect(@trocla.get_password('delete_test1','mysql')).to be_nil
+      end
+
+      it "deletes only a given format" do
+        expect(@trocla.password('delete_test2','mysql')).not_to be_nil
+        expect(@trocla.get_password('delete_test2','plain')).not_to be_nil
 
-    it "deletes only a given format" do
-      expect(@trocla.password('delete_test2','mysql')).not_to be_nil
-      expect(@trocla.get_password('delete_test2','plain')).not_to be_nil
+        @trocla.delete_password('delete_test2','plain')
+        expect(@trocla.get_password('delete_test2','plain')).to be_nil
+        expect(@trocla.get_password('delete_test2','mysql')).not_to be_nil
+      end
+
+      it "deletes only a given non-plain format" do
+        expect(@trocla.password('delete_test3','mysql')).not_to be_nil
+        expect(@trocla.get_password('delete_test3','plain')).not_to be_nil
 
-      @trocla.delete_password('delete_test2','plain')
-      expect(@trocla.get_password('delete_test2','plain')).to be_nil
-      expect(@trocla.get_password('delete_test2','mysql')).not_to be_nil
+        @trocla.delete_password('delete_test3','mysql')
+        expect(@trocla.get_password('delete_test3','mysql')).to be_nil
+        expect(@trocla.get_password('delete_test3','plain')).not_to be_nil
+      end
     end
 
-    it "deletes only a given non-plain format" do
-      expect(@trocla.password('delete_test3','mysql')).not_to be_nil
-      expect(@trocla.get_password('delete_test3','plain')).not_to be_nil
+    context 'concurrent access' do
+      context 'on expensive flagged formats' do
+        before(:each) do
+          expect(Trocla::Formats).to receive(:[]).with('sleep').at_least(:once).and_return(Trocla::Formats::Sleep)
+          expect(Trocla::Formats::Sleep).to receive(:expensive?).at_least(:once).and_return(true)
+          expect(Trocla::Formats).to receive(:available?).with('sleep').at_least(:once).and_return(true)
+        end
+        it 'should not overwrite a value if it takes longer' do
+          t1 = Thread.new{ @trocla.password('threadpwd','sleep','sleep' => 4) }
+          t2 = Thread.new{ @trocla.password('threadpwd','sleep','sleep' => 1) }
+          pwd1 = t1.value
+          pwd2 = t2.value
+          real_value = @trocla.password('threadpwd','sleep')
+          # as t2 finished first this should win
+          expect(pwd1).to eql(pwd2)
+          expect(real_value).to eql(pwd1)
+          expect(real_value).to eql(pwd2)
+        end
+      end
+      context 'on inexpensive flagged formats' do
+        before(:each) do
+          expect(Trocla::Formats).to receive(:[]).with('sleep').at_least(:once).and_return(Trocla::Formats::Sleep)
+          expect(Trocla::Formats::Sleep).to receive(:expensive?).at_least(:once).and_return(false)
+          expect(Trocla::Formats).to receive(:available?).with('sleep').at_least(:once).and_return(true)
+        end
+        it 'should not overwrite a value if it takes longer' do
+          t1 = Thread.new{ @trocla.password('threadpwd_inexp','sleep','sleep' => 4) }
+          t2 = Thread.new{ @trocla.password('threadpwd_inexp','sleep','sleep' => 1) }
+          pwd1 = t1.value
+          pwd2 = t2.value
+          real_value = @trocla.password('threadpwd_inexp','sleep')
+          # as t2 finished first but the format is inexpensive it gets overwritten
+          expect(pwd1).not_to eql(pwd2)
+          expect(real_value).to eql(pwd1)
+          expect(real_value).not_to eql(pwd2)
+        end
+      end
+      context 'real world example' do
+        it 'should store the quicker one' do
+          t1 = Thread.new{ @trocla.password('threadpwd_real','bcrypt','cost' => 17) }
+          t2 = Thread.new{ @trocla.password('threadpwd_real','bcrypt') }
+          pwd1 = t1.value
+          pwd2 = t2.value
+          real_value = @trocla.password('threadpwd_real','bcrypt')
+          # t2 should still win but both should be the same
+          expect(pwd1).to eql(pwd2)
+          expect(real_value).to eql(pwd1)
+          expect(real_value).to eql(pwd2)
+        end
+        it 'should store the quicker one test 2' do
+          t1 = Thread.new{ @trocla.password('my_shiny_selfsigned_ca', 'x509', {
+            'CN'        => 'This is my self-signed certificate',
+            'become_ca' => false,
+          }) }
+          t2 = Thread.new{ @trocla.password('my_shiny_selfsigned_ca', 'x509', {
+            'CN'        => 'This is my self-signed certificate',
+            'become_ca' => false,
+          }) }
+          cert1 = t1.value
+          cert2 = t2.value
+          real_value = @trocla.password('my_shiny_selfsigned_ca','x509')
+          # t2 should still win but both should be the same
+          expect(cert1).to eql(cert2)
+          expect(real_value).to eql(cert1)
+          expect(real_value).to eql(cert2)
+        end
+      end
+    end
 
-      @trocla.delete_password('delete_test3','mysql')
-      expect(@trocla.get_password('delete_test3','mysql')).to be_nil
-      expect(@trocla.get_password('delete_test3','plain')).not_to be_nil
+  end
+  context 'with .open' do
+    it 'closes the connection with a block' do
+      expect_any_instance_of(Trocla::Stores::Memory).to receive(:close)
+      Trocla.open{|t|
+        t.password('plain_open','plain')
+      }
+    end
+    it 'keeps the connection without a block' do
+      expect_any_instance_of(Trocla::Stores::Memory).not_to receive(:close)
+      Trocla.open.password('plain_open','plain')
     end
   end
 
diff -Nru trocla-0.2.3/.travis.yml trocla-0.3.0/.travis.yml
--- trocla-0.2.3/.travis.yml	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/.travis.yml	2021-05-04 15:31:47.000000000 -0400
@@ -1,10 +1,11 @@
 language: ruby
 sudo: false
 rvm:
+  - jruby
   - jruby-18mode
   - jruby-19mode
+  - 2.4.0
   - 2.2.0
-  - 2.1.0
   - 2.0.0
   - 1.9.3
   - 1.8.7
diff -Nru trocla-0.2.3/trocla.gemspec trocla-0.3.0/trocla.gemspec
--- trocla-0.2.3/trocla.gemspec	2016-03-01 15:40:25.000000000 -0500
+++ trocla-0.3.0/trocla.gemspec	2021-05-04 15:31:47.000000000 -0400
@@ -2,19 +2,19 @@
 # DO NOT EDIT THIS FILE DIRECTLY
 # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
 # -*- encoding: utf-8 -*-
-# stub: trocla 0.2.3 ruby lib
+# stub: trocla 0.3.0 ruby lib
 
 Gem::Specification.new do |s|
-  s.name = "trocla"
-  s.version = "0.2.3"
+  s.name = "trocla".freeze
+  s.version = "0.3.0"
 
-  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
-  s.require_paths = ["lib"]
-  s.authors = ["mh"]
-  s.date = "2016-02-15"
-  s.description = "Trocla helps you to generate random passwords and to store them in various formats (plain, MD5, bcrypt) for later retrival."
-  s.email = "[email protected]"
-  s.executables = ["trocla"]
+  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
+  s.require_paths = ["lib".freeze]
+  s.authors = ["mh".freeze]
+  s.date = "2017-08-04"
+  s.description = "Trocla helps you to generate random passwords and to store them in various formats (plain, MD5, bcrypt) for later retrival.".freeze
+  s.email = "[email protected]".freeze
+  s.executables = ["trocla".freeze]
   s.extra_rdoc_files = [
     "LICENSE.txt",
     "README.md"
@@ -64,39 +64,39 @@
     "spec/trocla_spec.rb",
     "trocla.gemspec"
   ]
-  s.homepage = "https://tech.immerda.ch/2011/12/trocla-get-hashed-passwords-out-of-puppet-manifests/";
-  s.licenses = ["GPLv3"]
-  s.rubygems_version = "2.2.2"
-  s.summary = "Trocla a simple password generator and storage"
+  s.homepage = "https://tech.immerda.ch/2011/12/trocla-get-hashed-passwords-out-of-puppet-manifests/".freeze
+  s.licenses = ["GPLv3".freeze]
+  s.rubygems_version = "2.6.11".freeze
+  s.summary = "Trocla a simple password generator and storage".freeze
 
   if s.respond_to? :specification_version then
     s.specification_version = 4
 
     if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
-      s.add_runtime_dependency(%q<moneta>, [">= 0"])
-      s.add_runtime_dependency(%q<highline>, [">= 0"])
-      s.add_runtime_dependency(%q<bcrypt>, [">= 0"])
-      s.add_development_dependency(%q<rspec>, [">= 0"])
-      s.add_development_dependency(%q<rdoc>, [">= 0"])
-      s.add_development_dependency(%q<jeweler>, [">= 0"])
-      s.add_development_dependency(%q<rspec-pending_for>, [">= 0"])
+      s.add_runtime_dependency(%q<moneta>.freeze, [">= 0"])
+      s.add_runtime_dependency(%q<highline>.freeze, [">= 0"])
+      s.add_runtime_dependency(%q<bcrypt>.freeze, [">= 0"])
+      s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
+      s.add_development_dependency(%q<rdoc>.freeze, [">= 0"])
+      s.add_development_dependency(%q<jeweler>.freeze, [">= 0"])
+      s.add_development_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
     else
-      s.add_dependency(%q<moneta>, [">= 0"])
-      s.add_dependency(%q<highline>, [">= 0"])
-      s.add_dependency(%q<bcrypt>, [">= 0"])
-      s.add_dependency(%q<rspec>, [">= 0"])
-      s.add_dependency(%q<rdoc>, [">= 0"])
-      s.add_dependency(%q<jeweler>, [">= 0"])
-      s.add_dependency(%q<rspec-pending_for>, [">= 0"])
+      s.add_dependency(%q<moneta>.freeze, [">= 0"])
+      s.add_dependency(%q<highline>.freeze, [">= 0"])
+      s.add_dependency(%q<bcrypt>.freeze, [">= 0"])
+      s.add_dependency(%q<rspec>.freeze, [">= 0"])
+      s.add_dependency(%q<rdoc>.freeze, [">= 0"])
+      s.add_dependency(%q<jeweler>.freeze, [">= 0"])
+      s.add_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
     end
   else
-    s.add_dependency(%q<moneta>, [">= 0"])
-    s.add_dependency(%q<highline>, [">= 0"])
-    s.add_dependency(%q<bcrypt>, [">= 0"])
-    s.add_dependency(%q<rspec>, [">= 0"])
-    s.add_dependency(%q<rdoc>, [">= 0"])
-    s.add_dependency(%q<jeweler>, [">= 0"])
-    s.add_dependency(%q<rspec-pending_for>, [">= 0"])
+    s.add_dependency(%q<moneta>.freeze, [">= 0"])
+    s.add_dependency(%q<highline>.freeze, [">= 0"])
+    s.add_dependency(%q<bcrypt>.freeze, [">= 0"])
+    s.add_dependency(%q<rspec>.freeze, [">= 0"])
+    s.add_dependency(%q<rdoc>.freeze, [">= 0"])
+    s.add_dependency(%q<jeweler>.freeze, [">= 0"])
+    s.add_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
   end
 end
 

Attachment: signature.asc
Description: PGP signature


--- End Message ---
--- Begin Message ---
Source: trocla
Source-Version: 0.5.0-1
Done: Jérôme Charaoui <[email protected]>

We believe that the bug you reported is fixed in the latest version of
trocla, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Jérôme Charaoui <[email protected]> (supplier of updated trocla package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Format: 1.8
Date: Sun, 29 Jan 2023 14:17:29 -0500
Source: trocla
Architecture: source
Version: 0.5.0-1
Distribution: unstable
Urgency: medium
Maintainer: Debian Ruby Team 
<[email protected]>
Changed-By: Jérôme Charaoui <[email protected]>
Closes: 988074 1008753 1010522
Changes:
 trocla (0.5.0-1) unstable; urgency=medium
 .
   * Team upload.
 .
   [ Debian Janitor ]
   * Update watch file format version to 4.
   * Bump debhelper from old 12 to 13.
 .
   [ Antoine Beaupré ]
   * Add myself to the uploaders, now that I am in the Ruby team
     (Closes: #1008753)
   * Acknowledge my own NMU (Closes: #988074)
   * New upstream release 0.4.0.
 .
   [ Jérôme Charaoui ]
   * New upstream release 0.5.0 (Closes: #1010522)
   * d/control:
     + add new dependencies for new upstream version
     + add wireguard-tools to Suggests
     + puppet is now puppet-agent
     + bump Standards-Version, no changes needed
     + flag test-only depends accordingly
     - fix ruby-interpreter-is-deprecated
     - ruby-mocha not needed anymore
   * d/patches:
     + new patches to fix gem requirements
     - remove patches adopted upstream
   * d/rules: use --gem-install for rubygems integration
Checksums-Sha1:
 2b716ce8b838d10a6afb8f68f86a47f20fd4cc66 1570 trocla_0.5.0-1.dsc
 425123c0c3c3d7c721d5c7db33c74a7f9599b390 31928 trocla_0.5.0.orig.tar.gz
 2859c743644d8b6c9139dc77db34fb19774e2453 3836 trocla_0.5.0-1.debian.tar.xz
 a4e695e630707a551924142b31c0a033e7ce5b77 9250 trocla_0.5.0-1_amd64.buildinfo
Checksums-Sha256:
 9663916aeb84a44ea570255124ceed8cb932aa16485a39c3008bec6cb065bea1 1570 
trocla_0.5.0-1.dsc
 02448fc27d3c3e31f5eda5f56804f1e399a85cb495dc1493c290162a86c9ff87 31928 
trocla_0.5.0.orig.tar.gz
 b717c40356f4b48f9ba866e30bee932cb231653d1b2621ddd719ab042ea95c48 3836 
trocla_0.5.0-1.debian.tar.xz
 453dec5895e52eff89b4c370792ed2981c1c5281abb102a1221435d9eea70c57 9250 
trocla_0.5.0-1_amd64.buildinfo
Files:
 c1b07afc5d9e4fa8a74ead54cef98496 1570 admin optional trocla_0.5.0-1.dsc
 2c2f70048b9ba5da263c22defcc8eec6 31928 admin optional trocla_0.5.0.orig.tar.gz
 e1d241b4f2d9b60b317fdb1559c341fa 3836 admin optional 
trocla_0.5.0-1.debian.tar.xz
 4e3361d9a8e960c9456656422388e203 9250 admin optional 
trocla_0.5.0-1_amd64.buildinfo

-----BEGIN PGP SIGNATURE-----

iHUEARYIAB0WIQTAq04Rv2xblqv/eu5pxS9ljpiFQgUCY9b9tgAKCRBpxS9ljpiF
Qk5EAP0bStCrkNbOIJXsA85vy/VB+aFY8aeEXwLLL2PYusqtBgD+LlGv0K97q3sc
9FKMEwX53j0k2+AZAha+s3H4yPlTnwg=
=/fkO
-----END PGP SIGNATURE-----

--- End Message ---

Reply via email to