dbi-dbrc 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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