dbi-dbrc 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ff5de96e8773faa52022e20fff1d008c360faa548ff65b9aac4a82b2a7e34b5
4
- data.tar.gz: dc7c04ad5ee358f59fca1a1c6331907a62e94177cdcc0cc2912eef9e204817c1
3
+ metadata.gz: 4f38085a9c7abb4c8a3e53fb239196135d317f78baa14a33f415fbaeab0b03d6
4
+ data.tar.gz: a591ba6877a994765c4ad4dc5eb540b149c98398fe11bfd93ff04be1dca4e562
5
5
  SHA512:
6
- metadata.gz: f5ca232636482744e5049a744b629f0fd7b956c511e3024d166ff633c68f3ca16fb089c2d5b126da676d09cc4cdf7ac11bc2b57a46c8b4f01846e4d982c6d9ab
7
- data.tar.gz: 9296fac30f6fc8a811e5e8cc1468a97d6da9ccb9a8155caecd1e61dc177f1599087191412cdfc294403cb73d6300c0d72e46ed9ba7ecaab15e22bc8c36f65371
6
+ metadata.gz: 607d4e9c54ceb5c98cfaa7dc1df75708b151daac57cca77bb244371d43a1950107334081cb65ea112ba46da85aa9b015700ad23df863a09f7cbd628b0627d069
7
+ data.tar.gz: 3712726dcf66e0f4dc19c4dbe46115e1dc9ea5159a59a4e9e31bf250e643dd07f114a6b4b27585a31c7a4c34016bba22c3999592b831feaea3aeeacddb9a57f4
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/CHANGES.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 1.6.0 - 9-Jun-2021
2
+ * Now supports gpg encrypted files, with a 4th optional parameter where you
3
+ can pass gpg options (usually a password, but whatever gpgme supports).
4
+ * Added gpgme as a dependency.
5
+ * Updated specs for MS Windows.
6
+ * The "home" handling is now a bit simpler, as it was originally written
7
+ before that method existed in core Ruby.
8
+
1
9
  ## 1.5.0 - 12-Apr-2021
2
10
  * Switched from test-unit to rspec, with corresponding changes in the
3
11
  gemspec and Rakefile.
data/Rakefile CHANGED
@@ -8,9 +8,9 @@ namespace :gem do
8
8
  desc "Create the dbi-dbrc gem"
9
9
  task :create => [:clean] do
10
10
  require 'rubygems/package'
11
- spec = eval(IO.read('dbi-dbrc.gemspec'))
11
+ spec = Gem::Specification.load('dbi-dbrc.gemspec')
12
12
  spec.signing_key = File.join(Dir.home, '.ssh', 'gem-private_key.pem')
13
- Gem::Package.build(spec, true)
13
+ Gem::Package.build(spec)
14
14
  end
15
15
 
16
16
  desc "Install the dbi-dbrc gem"
data/dbi-dbrc.gemspec CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'dbi-dbrc'
5
- spec.version = '1.5.0'
5
+ spec.version = '1.6.0'
6
6
  spec.author = 'Daniel Berger'
7
7
  spec.email = 'djberg96@gmail.com'
8
8
  spec.license = 'Apache-2.0'
@@ -12,6 +12,8 @@ Gem::Specification.new do |spec|
12
12
  spec.test_files = Dir['test/test*.rb']
13
13
  spec.cert_chain = Dir['certs/*']
14
14
 
15
+ spec.add_dependency('gpgme', '~> 2.0')
16
+
15
17
  spec.add_development_dependency('rake')
16
18
  spec.add_development_dependency('rspec', '~> 3.9')
17
19
  spec.add_development_dependency('fakefs', '~> 1.3')
@@ -19,7 +21,7 @@ Gem::Specification.new do |spec|
19
21
  spec.metadata = {
20
22
  'homepage_uri' => 'https://github.com/djberg96/dbi-dbrc',
21
23
  'bug_tracker_uri' => 'https://github.com/djberg96/dbi-dbrc/issues',
22
- 'changelog_uri' => 'https://github.com/djberg96/dbi-dbrc/blob/main/CHANGES',
24
+ 'changelog_uri' => 'https://github.com/djberg96/dbi-dbrc/blob/main/CHANGES.md',
23
25
  'documentation_uri' => 'https://github.com/djberg96/dbi-dbrc/wiki',
24
26
  'source_code_uri' => 'https://github.com/djberg96/dbi-dbrc',
25
27
  'wiki_uri' => 'https://github.com/djberg96/dbi-dbrc/wiki'
data/lib/dbi-dbrc.rb CHANGED
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'dbi/dbrc'
data/lib/dbi/dbrc.rb CHANGED
@@ -1,34 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  if File::ALT_SEPARATOR
2
4
  require 'win32/dir'
3
5
  require 'win32/file/attributes'
4
6
  require 'win32/process'
5
- require 'sys/admin'
6
7
  else
7
8
  require 'etc'
9
+ require 'gpgme'
8
10
  end
9
11
 
10
-
11
12
  # The DBI module serves as a namespace only.
12
13
  module DBI
13
-
14
14
  # The DBRC class encapsulates a database resource config file.
15
15
  class DBRC
16
-
17
16
  # This error is raised if anything fails trying to read the config file.
18
17
  class Error < StandardError; end
19
18
 
20
19
  # The version of the dbi-dbrc library
21
- VERSION = '1.5.0'.freeze
20
+ VERSION = '1.6.0'
22
21
 
23
22
  WINDOWS = File::ALT_SEPARATOR # :no-doc:
24
23
 
25
24
  # The database or host to be connected to.
26
25
  attr_accessor :database
27
26
 
28
- alias :db :database
29
- alias :db= :database=
30
- alias :host :database
31
- alias :host= :database=
27
+ alias db database
28
+ alias db= database=
29
+ alias host database
30
+ alias host= database=
32
31
 
33
32
  # The user name used for the database or host connection.
34
33
  attr_accessor :user
@@ -36,8 +35,8 @@ module DBI
36
35
  # The password associated with the database or host.
37
36
  attr_accessor :password
38
37
 
39
- alias :passwd :password
40
- alias :passwd= :password=
38
+ alias passwd password
39
+ alias passwd= password=
41
40
 
42
41
  # The driver associated with the database. This is used to internally to
43
42
  # construct the DSN.
@@ -49,14 +48,14 @@ module DBI
49
48
  # The maximum number of reconnects a program should make before giving up.
50
49
  attr_accessor :maximum_reconnects
51
50
 
52
- alias :max_reconn :maximum_reconnects
53
- alias :max_reconn= :maximum_reconnects=
51
+ alias max_reconn maximum_reconnects
52
+ alias max_reconn= maximum_reconnects=
54
53
 
55
54
  # The timeout, in seconds, for each connection attempt.
56
55
  attr_accessor :timeout
57
56
 
58
- alias :time_out :timeout
59
- alias :time_out= :timeout=
57
+ alias time_out timeout
58
+ alias time_out= timeout=
60
59
 
61
60
  # The interval, in seconds, between each connection attempt.
62
61
  attr_accessor :interval
@@ -78,7 +77,7 @@ module DBI
78
77
  # file.
79
78
  #
80
79
  # If an entry cannot be found for the database, or database plus user
81
- # combination, then a Error is raised. If the .dbrc file cannot be
80
+ # combination, then a Error is raised. If the .dbrc file cannot be
82
81
  # found, or is setup improperly with regards to permissions or properties
83
82
  # then a DBI::DBRC::Error is raised.
84
83
  #
@@ -88,6 +87,9 @@ module DBI
88
87
  # storage mechanism. In that case simply treat the 'database' as the
89
88
  # host name, and ignore the DBI::DBRC#dsn and DBI::DBRC#driver methods.
90
89
  #
90
+ # On unixy systems you can GPG encrypt the file, and this library will
91
+ # decrypt it for you based on the +gpg_options+ that you pass.
92
+ #
91
93
  # Examples:
92
94
  #
93
95
  # # Find the first match for 'some_database'
@@ -99,14 +101,11 @@ module DBI
99
101
  # # Find the first match for 'foo_user@some_database' under /usr/local
100
102
  # DBI::DBRC.new('some_database', 'foo_usr', '/usr/local')
101
103
  #
102
- def initialize(database, user=nil, dbrc_dir=nil)
104
+ # # Pass along a GPG password to decrypt the file.
105
+ # DBI::DBRC.new('some_database', 'foo_usr', '/usr/local', :gpg_options => {:password => 'xxx'})
106
+ #
107
+ def initialize(database, user = nil, dbrc_dir = Dir.home, gpg_options = nil)
103
108
  if dbrc_dir.nil?
104
- if WINDOWS
105
- home = Sys::Admin.get_user(Process.uid, :localaccount => true).dir
106
- else
107
- home = Dir.home(Etc.getpwuid.name)
108
- end
109
-
110
109
  # Default to the app data directory on Windows, or root on Unix, if
111
110
  # no home dir can be found.
112
111
  if home.nil?
@@ -145,14 +144,21 @@ module DBI
145
144
  File.decrypt(@dbrc_file)
146
145
  end
147
146
 
148
- parse_dbrc_config_file()
149
- validate_data()
150
- convert_numeric_strings()
151
- create_dsn_string()
152
- ensure
153
- if WINDOWS && file_was_encrypted
154
- File.encrypt(@dbrc_file)
147
+ if gpg_options
148
+ require 'gpgme'
149
+ require 'stringio'
150
+ crypto = GPGME::Crypto.new(gpg_options)
151
+ stringio = crypto.decrypt(File.open(@dbrc_file))
152
+ parse_dbrc_config_file(StringIO.new(stringio.read))
153
+ else
154
+ parse_dbrc_config_file
155
155
  end
156
+
157
+ validate_data
158
+ convert_numeric_strings
159
+ create_dsn_string
160
+ ensure
161
+ File.encrypt(@dbrc_file) if WINDOWS && file_was_encrypted
156
162
  end
157
163
  end
158
164
 
@@ -160,28 +166,23 @@ module DBI
160
166
  # Ruby Object#inspect, except that the password field is filtered.
161
167
  #
162
168
  def inspect
163
- str = instance_variables.map{ |iv|
169
+ str = instance_variables.map do |iv|
164
170
  if iv == '@password'
165
171
  "#{iv}=[FILTERED]"
166
172
  else
167
173
  "#{iv}=#{instance_variable_get(iv).inspect}"
168
174
  end
169
- }.join(', ')
175
+ end.join(', ')
170
176
 
171
- "#<#{self.class}:0x#{(self.object_id*2).to_s(16)} " << str << ">"
177
+ "#<#{self.class}:0x#{(object_id * 2).to_s(16)} " + str + '>'
172
178
  end
173
179
 
174
180
  private
175
181
 
176
182
  # Ensure that the user/password has been set
177
183
  def validate_data
178
- unless @user
179
- raise Error, "no user found associated with #{@database}"
180
- end
181
-
182
- unless @password
183
- raise Error, "password not defined for #{@user}@#{@database}"
184
- end
184
+ raise Error, "no user found associated with #{@database}" unless @user
185
+ raise Error, "password not defined for #{@user}@#{@database}" unless @password
185
186
  end
186
187
 
187
188
  # Converts strings that should be numbers into actual numbers
@@ -197,87 +198,80 @@ module DBI
197
198
  end
198
199
 
199
200
  # Check ownership and permissions
200
- def check_file(file=@dbrc_file)
201
- File.open(file){ |f|
201
+ def check_file(file = @dbrc_file)
202
+ File.open(file) do |f|
202
203
  # Permissions must be set to 600 or better on Unix systems.
203
204
  # Must be hidden on Win32 systems.
204
205
  if WINDOWS
205
- unless File.hidden?(file)
206
- raise Error, "The .dbrc file must be hidden"
207
- end
206
+ raise Error, 'The .dbrc file must be hidden' unless File.hidden?(file)
208
207
  else
209
- unless (f.stat.mode & 077) == 0
210
- raise Error, "Bad .dbrc file permissions"
211
- end
208
+ raise Error, 'Bad .dbrc file permissions' unless (f.stat.mode & 0o77) == 0
212
209
  end
213
210
 
214
211
  # Only the owner may use it
215
- unless f.stat.owned?
216
- raise Error, "Not owner of .dbrc file"
217
- end
218
- }
212
+ raise Error, 'Not owner of .dbrc file' unless f.stat.owned?
213
+ end
219
214
  end
220
215
 
221
216
  # Parse the text out of the .dbrc file. This is the only method you
222
217
  # need to redefine if writing your own config handler.
223
- def parse_dbrc_config_file(file=@dbrc_file)
224
- File.foreach(file){ |line|
225
- next if line =~ /^#/ # Ignore comments
226
- db, user, pwd, driver, timeout, max, interval = line.split
227
-
228
- next unless @database == db
229
-
230
- if @user
231
- next unless @user == user
218
+ def parse_dbrc_config_file(file = @dbrc_file)
219
+ begin
220
+ fh = file.is_a?(StringIO) ? file : File.open(file)
221
+
222
+ fh.each_line do |line|
223
+ next if line =~ /^#/ # Ignore comments
224
+ db, user, pwd, driver, timeout, max, interval = line.split
225
+
226
+ next unless @database == db
227
+ next if @user && @user != user
228
+
229
+ @user = user
230
+ @password = pwd
231
+ @driver = driver
232
+ @timeout = timeout
233
+ @maximum_reconnects = max
234
+ @interval = interval
235
+ break
232
236
  end
237
+ ensure
238
+ fh.close if fh && fh.respond_to?(:close)
239
+ end
233
240
 
234
- @user = user
235
- @password = pwd
236
- @driver = driver
237
- @timeout = timeout
238
- @maximum_reconnects = max
239
- @interval = interval
240
- return
241
- }
242
-
243
- # If we reach here it means the database and/or user wasn't found
244
241
  if @user
245
- err = "no record found for #{@user}@#{@database}"
242
+ raise Error, "no record found for #{@user}@#{@database}" unless @user
246
243
  else
247
- err = "no record found for #{@database}"
244
+ raise Error, "no record found for #{@database}" unless @database
248
245
  end
249
-
250
- raise Error, err
251
246
  end
252
-
253
247
  end
254
248
 
255
249
  # A subclass of DBRC designed to handle .dbrc files in XML format. The
256
250
  # public methods of this class are identical to DBRC.
257
251
  class DBRC::XML < DBRC
258
252
  require 'rexml/document' # Good enough for small files
259
- include REXML
260
253
 
261
254
  private
262
255
 
263
- def parse_dbrc_config_file(file=@dbrc_file)
264
- doc = Document.new(File.new(file))
265
- fields = %w/user password driver interval timeout maximum_reconnects/
266
- doc.elements.each("/dbrc/database"){ |element|
267
- next unless element.attributes["name"] == database
268
- if @user
269
- next unless element.elements["user"].text == @user
270
- end
271
- fields.each{ |field|
256
+ def parse_dbrc_config_file(file = @dbrc_file)
257
+ file = file.is_a?(StringIO) ? file : File.new(file)
258
+ doc = REXML::Document.new(file)
259
+
260
+ fields = %w[user password driver interval timeout maximum_reconnects]
261
+
262
+ doc.elements.each('/dbrc/database') do |element|
263
+ next unless element.attributes['name'] == database
264
+ next if @user && @user != element.elements['user'].text
265
+
266
+ fields.each do |field|
272
267
  val = element.elements[field]
273
- unless val.nil?
274
- send("#{field}=",val.text)
275
- end
276
- }
277
- return
278
- }
279
- # If we reach here it means the database and/or user wasn't found
280
- raise Error, "No record found for #{@user}@#{@database}"
268
+ send("#{field}=", val.text) unless val.nil?
269
+ end
270
+
271
+ break
272
+ end
273
+
274
+ raise Error, "No record found for #{@user}@#{@database}" unless @user && @database
281
275
  end
282
276
  end
283
277
 
@@ -288,23 +282,25 @@ module DBI
288
282
 
289
283
  private
290
284
 
291
- def parse_dbrc_config_file(file=@dbrc_file)
292
- config = YAML.load(File.open(file))
293
- config.each{ |hash|
294
- hash.each{ |db,info|
285
+ def parse_dbrc_config_file(file = @dbrc_file)
286
+ fh = file.is_a?(StringIO) ? file : File.open(file)
287
+ config = YAML.safe_load(fh)
288
+
289
+ config.each do |hash|
290
+ hash.each do |db, info|
295
291
  next unless db == @database
296
- next unless @user == info["user"] if @user
297
- @user = info["user"]
298
- @password = info["password"]
299
- @driver = info["driver"]
300
- @interval = info["interval"]
301
- @timeout = info["timeout"]
302
- @maximum_reconnects = info["maximum_reconnects"]
303
- return
304
- }
305
- }
306
- # If we reach this point, it means the database wasn't found
307
- raise Error, "No entry found for #{@user}@#{@database}"
292
+ next if @user && @user != info['user']
293
+ @user = info['user']
294
+ @password = info['password']
295
+ @driver = info['driver']
296
+ @interval = info['interval']
297
+ @timeout = info['timeout']
298
+ @maximum_reconnects = info['maximum_reconnects']
299
+ break
300
+ end
301
+ end
302
+
303
+ raise Error, "No entry found for #{@user}@#{@database}" unless @user && @database
308
304
  end
309
305
  end
310
306
  end
@@ -43,19 +43,26 @@ RSpec.describe DBI::DBRC do
43
43
  end
44
44
 
45
45
  example "version" do
46
- expect(described_class::VERSION).to eq('1.5.0')
46
+ expect(described_class::VERSION).to eq('1.6.0')
47
47
  expect(described_class::VERSION).to be_frozen
48
48
  end
49
49
 
50
50
  context "windows", :windows => true do
51
51
  example "constructor raises an error unless the .dbrc file is hidden" do
52
- File.unset_attr(plain, File::HIDDEN)
52
+ allow(FakeFS::File).to receive(:hidden?).and_return(false)
53
53
  expect{ described_class.new(db_foo, user1) }.to raise_error(described_class::Error)
54
54
  end
55
55
  end
56
56
 
57
57
  context "constructor" do
58
- example "constructor raises an error if the permissions are invalid" do
58
+ before do
59
+ if File::ALT_SEPARATOR
60
+ allow(FakeFS::File).to receive(:hidden?).and_return(true)
61
+ allow(FakeFS::File).to receive(:encrypted?).and_return(false)
62
+ end
63
+ end
64
+
65
+ example "constructor raises an error if the permissions are invalid", :unix => true do
59
66
  File.chmod(0555, dbrc)
60
67
  expect{ described_class.new(db_foo, user1) }.to raise_error(described_class::Error)
61
68
  end
@@ -111,6 +118,10 @@ RSpec.describe DBI::DBRC do
111
118
 
112
119
  context "instance methods" do
113
120
  before do
121
+ if File::ALT_SEPARATOR
122
+ allow(FakeFS::File).to receive(:hidden?).and_return(true)
123
+ allow(FakeFS::File).to receive(:encrypted?).and_return(false)
124
+ end
114
125
  @dbrc = DBI::DBRC.new(db_foo)
115
126
  end
116
127
 
@@ -55,6 +55,12 @@ RSpec.describe DBI::DBRC::XML, :xml => true do
55
55
 
56
56
  before do
57
57
  allow(Dir).to receive(:home).and_return(home)
58
+
59
+ if File::ALT_SEPARATOR
60
+ allow(FakeFS::File).to receive(:hidden?).and_return(true)
61
+ allow(FakeFS::File).to receive(:encrypted?).and_return(false)
62
+ end
63
+
58
64
  FileUtils.mkdir_p(home)
59
65
  File.open(dbrc, 'w'){ |fh| fh.write(xml) }
60
66
  File.chmod(0600, dbrc)
@@ -49,6 +49,12 @@ RSpec.describe DBI::DBRC::YML, :yml => true do
49
49
 
50
50
  before do
51
51
  allow(Dir).to receive(:home).and_return(home)
52
+
53
+ if File::ALT_SEPARATOR
54
+ allow(FakeFS::File).to receive(:hidden?).and_return(true)
55
+ allow(FakeFS::File).to receive(:encrypted?).and_return(false)
56
+ end
57
+
52
58
  FileUtils.mkdir_p(home)
53
59
  File.open(dbrc, 'w'){ |fh| fh.write(yml) }
54
60
  File.chmod(0600, dbrc)
data/spec/spec_helper.rb CHANGED
@@ -2,4 +2,5 @@ require 'rspec'
2
2
 
3
3
  RSpec.configure do |config|
4
4
  config.filter_run_excluding(:windows) if RbConfig::CONFIG['host_os'] !~ /mswin|win32|dos|mingw|cygwin/i
5
+ config.filter_run_excluding(:unix) if RbConfig::CONFIG['host_os'] =~ /mswin|win32|dos|mingw|cygwin/i
5
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbi-dbrc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Berger
@@ -35,8 +35,22 @@ cert_chain:
35
35
  ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
36
36
  WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
37
37
  -----END CERTIFICATE-----
38
- date:
38
+ date: 2021-06-09 00:00:00.000000000 Z
39
39
  dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: gpgme
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.0'
40
54
  - !ruby/object:Gem::Dependency
41
55
  name: rake
42
56
  requirement: !ruby/object:Gem::Requirement
@@ -93,37 +107,29 @@ executables: []
93
107
  extensions: []
94
108
  extra_rdoc_files: []
95
109
  files:
96
- - dbi-dbrc.gemspec
97
- - spec
98
- - spec/spec_helper.rb
99
- - spec/dbi_dbrc_yml_spec.rb
100
- - spec/dbi_dbrc_spec.rb
101
- - spec/dbi_dbrc_xml_spec.rb
110
+ - CHANGES.md
111
+ - Gemfile
112
+ - MANIFEST.md
102
113
  - README.md
103
114
  - Rakefile
104
- - MANIFEST.md
105
- - certs
106
115
  - certs/djberg96_pub.pem
107
- - examples
108
- - examples/plain
116
+ - dbi-dbrc.gemspec
109
117
  - examples/plain/test.rb
110
- - examples/xml
111
118
  - examples/xml/test_xml.rb
112
- - examples/yml
113
119
  - examples/yml/test_yml.rb
114
- - lib
115
- - lib/dbi
116
- - lib/dbi/dbrc.rb
117
120
  - lib/dbi-dbrc.rb
118
- - Gemfile
119
- - CHANGES.md
121
+ - lib/dbi/dbrc.rb
122
+ - spec/dbi_dbrc_spec.rb
123
+ - spec/dbi_dbrc_xml_spec.rb
124
+ - spec/dbi_dbrc_yml_spec.rb
125
+ - spec/spec_helper.rb
120
126
  homepage: https://github.com/djberg96/dbi-dbrc
121
127
  licenses:
122
128
  - Apache-2.0
123
129
  metadata:
124
130
  homepage_uri: https://github.com/djberg96/dbi-dbrc
125
131
  bug_tracker_uri: https://github.com/djberg96/dbi-dbrc/issues
126
- changelog_uri: https://github.com/djberg96/dbi-dbrc/blob/main/CHANGES
132
+ changelog_uri: https://github.com/djberg96/dbi-dbrc/blob/main/CHANGES.md
127
133
  documentation_uri: https://github.com/djberg96/dbi-dbrc/wiki
128
134
  source_code_uri: https://github.com/djberg96/dbi-dbrc
129
135
  wiki_uri: https://github.com/djberg96/dbi-dbrc/wiki
metadata.gz.sig CHANGED
Binary file