unixconfigstyle 1.0.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.
- data/lib/unixconfigstyle.rb +418 -0
- data/tests/test-unixconfigstyle.rb +22 -0
- metadata +49 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
## Author: Erwan SEITE
|
|
3
|
+
## Aim: Read or Write config files written in Unix Style
|
|
4
|
+
## Licence : GPL v2
|
|
5
|
+
## Source : https://github.com/wanix/ruby-UnixConfigStyle
|
|
6
|
+
## The section name "[-UnixConfigStyle-]" is reserved for the global one
|
|
7
|
+
###############################################################################
|
|
8
|
+
class UnixConfigStyle
|
|
9
|
+
|
|
10
|
+
Version = '1.0'
|
|
11
|
+
|
|
12
|
+
@@rootsection="[-UnixConfigStyle-]"
|
|
13
|
+
|
|
14
|
+
@@regexpStruct={}
|
|
15
|
+
#Empty line definition
|
|
16
|
+
@@regexpStruct[:emptyline] = /^\s*$/
|
|
17
|
+
#Comment line definition
|
|
18
|
+
@@regexpStruct[:commentline] = /^\s*[#;]/
|
|
19
|
+
#Section Line definition
|
|
20
|
+
@@regexpStruct[:sectionline] = /^\s*\[(.+?)\]\s*([#;].*)?$/
|
|
21
|
+
#Parameter line definition
|
|
22
|
+
@@regexpStruct[:paramline] = /^\s*([\d\w\-]+)\s*=.*$/
|
|
23
|
+
@@regexpStruct[:paramlinequote] = /^\s*([\d\w\-]+)\s*=\s*('.*')\s*([#;].*)?$/
|
|
24
|
+
@@regexpStruct[:paramline2quote] = /^\s*([\d\w\-]+)\s*=\s*(".*")\s*([#;].*)?$/
|
|
25
|
+
@@regexpStruct[:paramlinenormal] = /^\s*([\d\w\-]+)\s*=\s*(.*?)\s*([#;].*)?$/
|
|
26
|
+
|
|
27
|
+
#(private) Initialise the class and read the file
|
|
28
|
+
#Parameters:
|
|
29
|
+
# config_file: String (path to a readable unix config file) (optionnal)
|
|
30
|
+
def initialize(config_file=nil)
|
|
31
|
+
@sections = {}
|
|
32
|
+
|
|
33
|
+
if(config_file)
|
|
34
|
+
push_unix_config_file(config_file)
|
|
35
|
+
end
|
|
36
|
+
end #initialize
|
|
37
|
+
private :initialize
|
|
38
|
+
|
|
39
|
+
#(private) Validate a file is readable
|
|
40
|
+
#Parameters:
|
|
41
|
+
# fileToRead: String (path to a readable file)
|
|
42
|
+
def validate(fileToRead)
|
|
43
|
+
unless File.readable?(fileToRead)
|
|
44
|
+
raise Errno::EACCES, "Can't read #{fileToRead}"
|
|
45
|
+
end
|
|
46
|
+
end #validate
|
|
47
|
+
private :validate
|
|
48
|
+
|
|
49
|
+
#Read a config file and add its properties to the end of the object ones
|
|
50
|
+
#Parameters:
|
|
51
|
+
# config_file: String (path to a readable unix config file)
|
|
52
|
+
def push_unix_config_file(config_file)
|
|
53
|
+
add_unix_config_file(config_file,"push")
|
|
54
|
+
end #push_unix_config_file
|
|
55
|
+
|
|
56
|
+
#Read a config file and add its properties to the start of the object ones
|
|
57
|
+
#Parameters:
|
|
58
|
+
# config_file: String (path to a readable unix config file)
|
|
59
|
+
def insert_unix_config_file(config_file)
|
|
60
|
+
add_unix_config_file(config_file,"insert")
|
|
61
|
+
end #insert_unix_config_file
|
|
62
|
+
|
|
63
|
+
#(private) read a config file and add its properties to the current object
|
|
64
|
+
#Parameters:
|
|
65
|
+
# config_file: String (path to a readable unix config file)
|
|
66
|
+
# operation: String [push|insert]
|
|
67
|
+
def add_unix_config_file(config_file, operation="push")
|
|
68
|
+
if operation != "push" and operation != "insert"
|
|
69
|
+
raise ArgumentError, "operation #{operation} not allowed", caller
|
|
70
|
+
end
|
|
71
|
+
validate(config_file)
|
|
72
|
+
|
|
73
|
+
file = File.open(config_file, 'r')
|
|
74
|
+
|
|
75
|
+
@sections[@@rootsection]={} unless @sections.key?(@@rootsection)
|
|
76
|
+
currentSection=@@rootsection
|
|
77
|
+
|
|
78
|
+
while !file.eof?
|
|
79
|
+
line = file.readline
|
|
80
|
+
#We ignore the empty lines
|
|
81
|
+
next if @@regexpStruct[:emptyline].match(line)
|
|
82
|
+
#We ignore the comment lines
|
|
83
|
+
next if @@regexpStruct[:commentline].match(line)
|
|
84
|
+
#Change the current section if a new line section is matched
|
|
85
|
+
sectionmatch = @@regexpStruct[:sectionline].match(line)
|
|
86
|
+
if sectionmatch
|
|
87
|
+
currentSection=sectionmatch[1]
|
|
88
|
+
#If this section is seen for the first time, initialise the hash
|
|
89
|
+
@sections[currentSection]={} unless @sections.key?(currentSection)
|
|
90
|
+
next
|
|
91
|
+
end
|
|
92
|
+
#Now we have to recognize the line or there is an error in the file ... or a bug here :)
|
|
93
|
+
paramlinematch = @@regexpStruct[:paramline].match(line)
|
|
94
|
+
if paramlinematch
|
|
95
|
+
#First time this param is seen ?
|
|
96
|
+
@sections[currentSection][paramlinematch[1]]=[] unless @sections[currentSection].key?(paramlinematch[1])
|
|
97
|
+
parammatch = @@regexpStruct[:paramlinequote].match(line)
|
|
98
|
+
if parammatch
|
|
99
|
+
if operation == "push"
|
|
100
|
+
@sections[currentSection][paramlinematch[1]].push(parammatch[2])
|
|
101
|
+
elsif operation == "insert"
|
|
102
|
+
@sections[currentSection][paramlinematch[1]].insert(0,parammatch[2])
|
|
103
|
+
end
|
|
104
|
+
next
|
|
105
|
+
end
|
|
106
|
+
parammatch = @@regexpStruct[:paramline2quote].match(line)
|
|
107
|
+
if parammatch
|
|
108
|
+
if operation == "push"
|
|
109
|
+
@sections[currentSection][paramlinematch[1]].push(parammatch[2])
|
|
110
|
+
elsif operation == "insert"
|
|
111
|
+
@sections[currentSection][paramlinematch[1]].insert(0,parammatch[2])
|
|
112
|
+
end
|
|
113
|
+
next
|
|
114
|
+
end
|
|
115
|
+
parammatch = @@regexpStruct[:paramlinenormal].match(line)
|
|
116
|
+
if parammatch
|
|
117
|
+
if operation == "push"
|
|
118
|
+
@sections[currentSection][paramlinematch[1]].push(parammatch[2])
|
|
119
|
+
elsif operation == "insert"
|
|
120
|
+
@sections[currentSection][paramlinematch[1]].insert(0,parammatch[2])
|
|
121
|
+
end
|
|
122
|
+
next
|
|
123
|
+
end
|
|
124
|
+
else
|
|
125
|
+
warn("[warning] unrecognized line "+file.lineno.to_s+" in "+@unix_config_file+" : "+line)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
file.close()
|
|
129
|
+
end
|
|
130
|
+
private :add_unix_config_file
|
|
131
|
+
|
|
132
|
+
#Write the object in a file
|
|
133
|
+
#Parameters:
|
|
134
|
+
# fileToWrite : String, path to a file
|
|
135
|
+
# comment: String (optionnal)
|
|
136
|
+
def write (fileToWrite, comment=nil)
|
|
137
|
+
File.open(fileToWrite,'w') do |file|
|
|
138
|
+
self.print(comment, file)
|
|
139
|
+
end
|
|
140
|
+
end #def write
|
|
141
|
+
|
|
142
|
+
#Print the object in a unix config style into an IO obj
|
|
143
|
+
#Parameters:
|
|
144
|
+
# comment: String
|
|
145
|
+
# io_obj : IO (default stdout)
|
|
146
|
+
def print (comment=nil, io_obj=$stdout)
|
|
147
|
+
raise ArgumentError, 'the argument "comment" must be a String' unless (comment.is_a? String or comment == nil)
|
|
148
|
+
raise ArgumentError, 'the argument "io_obj" must be an IO class or an IO inherited class' unless io_obj.is_a? IO
|
|
149
|
+
if comment
|
|
150
|
+
io_obj.puts "##{comment}"
|
|
151
|
+
end
|
|
152
|
+
if @sections.key?(@@rootsection)
|
|
153
|
+
@sections[@@rootsection].keys.each do |param_key|
|
|
154
|
+
@sections[@@rootsection][param_key].each do |param_value|
|
|
155
|
+
io_obj.puts "#{param_key}=#{param_value}"
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
@sections.keys.each do |section_key|
|
|
160
|
+
if section_key == @@rootsection
|
|
161
|
+
next
|
|
162
|
+
end
|
|
163
|
+
io_obj.puts "[#{section_key}]"
|
|
164
|
+
@sections[section_key].keys.each do |param_key|
|
|
165
|
+
@sections[section_key][param_key].each do |param_value|
|
|
166
|
+
io_obj.puts "#{param_key}=#{param_value}"
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end #def print
|
|
171
|
+
|
|
172
|
+
#Get all avalaibles sections (all but root one)
|
|
173
|
+
#return an array
|
|
174
|
+
def getSections ()
|
|
175
|
+
allsections = @sections.keys
|
|
176
|
+
if allsections
|
|
177
|
+
allsections.delete(@@rootsection)
|
|
178
|
+
end
|
|
179
|
+
return allsections
|
|
180
|
+
end #def getSections
|
|
181
|
+
|
|
182
|
+
#Get all avalaibles keys for this section
|
|
183
|
+
#return an array (or nil if no keys found)
|
|
184
|
+
#Parameters:
|
|
185
|
+
# section: String (optionnal)
|
|
186
|
+
def getKeys (section=@@rootsection)
|
|
187
|
+
if @sections.key?(section)
|
|
188
|
+
return @sections[section].keys
|
|
189
|
+
end
|
|
190
|
+
return nil
|
|
191
|
+
end #def getKeys
|
|
192
|
+
|
|
193
|
+
#Get all differents keys in the object
|
|
194
|
+
# if section is defined, return a merged array for keys in the section and keys in root section
|
|
195
|
+
# if section is not defined, return a a merged array for all keys in the object
|
|
196
|
+
#return an array (or nil if no keys found)
|
|
197
|
+
def getAllKeys (section=nil)
|
|
198
|
+
allKeys=[]
|
|
199
|
+
#Get keys from root section
|
|
200
|
+
allKeys.concat(@sections[@@rootsection].keys) if @sections.key?(@@rootsection)
|
|
201
|
+
if ( section == nil )
|
|
202
|
+
#Get keys from the others sections if exists and are not empty
|
|
203
|
+
if self.haveSections?()
|
|
204
|
+
self.getSections().each do |subsection|
|
|
205
|
+
allKeys.concat(@sections[subsection].keys) if @sections.key?(subsection)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
else
|
|
209
|
+
#get keys for this specific section
|
|
210
|
+
allKeys.concat(@sections[section].keys) if self.sectionExists?(section)
|
|
211
|
+
end
|
|
212
|
+
return nil if allKeys.empty?()
|
|
213
|
+
allKeys.uniq!
|
|
214
|
+
return allKeys
|
|
215
|
+
end #getAllKeys
|
|
216
|
+
|
|
217
|
+
#Add values for a key
|
|
218
|
+
#Parameters:
|
|
219
|
+
# values: Array or String
|
|
220
|
+
# key: String
|
|
221
|
+
# section: String (optionnal)
|
|
222
|
+
def addValues (values, key, section=@@rootsection)
|
|
223
|
+
@sections[section]={} unless @sections.key?(section)
|
|
224
|
+
@sections[section][key]=[] unless @sections[section].key?(key)
|
|
225
|
+
if values.is_a? Array
|
|
226
|
+
return true if @sections[section][key].concat(values)
|
|
227
|
+
else
|
|
228
|
+
#String
|
|
229
|
+
return true if @sections[section][key].push(values)
|
|
230
|
+
end
|
|
231
|
+
return false
|
|
232
|
+
end #def addValues
|
|
233
|
+
|
|
234
|
+
#Insert values for a key
|
|
235
|
+
#Parameters:
|
|
236
|
+
# values: Array or String
|
|
237
|
+
# key: String
|
|
238
|
+
# section: String (optionnal)
|
|
239
|
+
def insertValues (values, key, section=@@rootsection)
|
|
240
|
+
@sections[section]={} unless @sections.key?(section)
|
|
241
|
+
@sections[section][key]=[] unless @sections[section].key?(key)
|
|
242
|
+
if @sections[section][key].insert(0,values)
|
|
243
|
+
return true
|
|
244
|
+
else
|
|
245
|
+
return false
|
|
246
|
+
end
|
|
247
|
+
end #insertValues
|
|
248
|
+
|
|
249
|
+
#Get all values for a key (in a section if given, else in root one)
|
|
250
|
+
#Parameters:
|
|
251
|
+
# key: String
|
|
252
|
+
# section: String (optionnal)
|
|
253
|
+
# globalSearch: boolean, if true, insert the results from the root section (default false)
|
|
254
|
+
def getValues (key, section=@@rootsection, globalSearch=false)
|
|
255
|
+
resultArray=[]
|
|
256
|
+
if (globalSearch == true and section != @@rootsection)
|
|
257
|
+
#We put first the result form the root section
|
|
258
|
+
resultArray.concat(@sections[@@rootsection][key]) if ( @sections.key?(@@rootsection) and @sections[@@rootsection].key?(key) )
|
|
259
|
+
end
|
|
260
|
+
resultArray.concat(@sections[section][key]) if ( @sections.key?(section) and @sections[section].key?(key) )
|
|
261
|
+
return nil if resultArray.empty?()
|
|
262
|
+
return resultArray
|
|
263
|
+
end #getValues
|
|
264
|
+
|
|
265
|
+
#Get the first value for a key (config first win)
|
|
266
|
+
#Parameters:
|
|
267
|
+
# key: String
|
|
268
|
+
# section: String (optionnal)
|
|
269
|
+
def getFirstValue (key, section=@@rootsection)
|
|
270
|
+
if @sections.key?(section)
|
|
271
|
+
if @sections[section].key?(key)
|
|
272
|
+
return @sections[section][key].first
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
return nil
|
|
276
|
+
end #getFirstValue
|
|
277
|
+
|
|
278
|
+
#Get the last value for a key (config last win)
|
|
279
|
+
#Parameters:
|
|
280
|
+
# key: String
|
|
281
|
+
# section: String (optionnal)
|
|
282
|
+
def getLastValue (key, section=@@rootsection)
|
|
283
|
+
if @sections.key?(section)
|
|
284
|
+
if @sections[section].key?(key)
|
|
285
|
+
return @sections[section][key].last
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
return nil
|
|
289
|
+
end #getLastValue
|
|
290
|
+
|
|
291
|
+
#Get the value with the given index for a key
|
|
292
|
+
#Parameters:
|
|
293
|
+
# key: String
|
|
294
|
+
# index :Integer (default 0)
|
|
295
|
+
# section: String (optionnal)
|
|
296
|
+
def getValue (key, index=0, section=@@rootsection)
|
|
297
|
+
if @sections.key?(section)
|
|
298
|
+
if @sections[section].key?(key)
|
|
299
|
+
return @sections[section][key][index]
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
return nil
|
|
303
|
+
end #getValue
|
|
304
|
+
|
|
305
|
+
#Replace the first value by the given one
|
|
306
|
+
#Parameters:
|
|
307
|
+
# newvalue : string
|
|
308
|
+
# key: String
|
|
309
|
+
# section: String (optionnal)
|
|
310
|
+
def replaceFirstValue (newvalue, key, section=@@rootsection)
|
|
311
|
+
if @sections.key?(section)
|
|
312
|
+
if @sections[section].key?(key)
|
|
313
|
+
@sections[section][key].first.replace(newvalue)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
return nil
|
|
317
|
+
end #replaceFirstValue
|
|
318
|
+
|
|
319
|
+
#Replace the last value by the given one
|
|
320
|
+
#Parameters:
|
|
321
|
+
# newvalue : string
|
|
322
|
+
# key: String
|
|
323
|
+
# section: String (optionnal)
|
|
324
|
+
def replaceLastValue (newvalue, key, section=@@rootsection)
|
|
325
|
+
if @sections.key?(section)
|
|
326
|
+
if @sections[section].key?(key)
|
|
327
|
+
@sections[section][key].last.replace(newvalue)
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
return nil
|
|
331
|
+
end #replaceLastValue
|
|
332
|
+
|
|
333
|
+
#Replace the value by the given one
|
|
334
|
+
#Parameters:
|
|
335
|
+
# newvalue : string
|
|
336
|
+
# key: String
|
|
337
|
+
# index :Integer (default 0)
|
|
338
|
+
# section: String (optionnal)
|
|
339
|
+
def replaceValue (newvalue, key, index=0, section=@@rootsection)
|
|
340
|
+
if @sections.key?(section)
|
|
341
|
+
if @sections[section].key?(key)
|
|
342
|
+
@sections[section][key][index].replace(newvalue)
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
return nil
|
|
346
|
+
end #replaceValue
|
|
347
|
+
|
|
348
|
+
#Replace all the value array by the given one
|
|
349
|
+
#Parameters:
|
|
350
|
+
# newvalues : Array
|
|
351
|
+
# key: String
|
|
352
|
+
# section: String (optionnal)
|
|
353
|
+
def replaceValues (newvalues, key, section=@@rootsection)
|
|
354
|
+
if @sections.key?(section)
|
|
355
|
+
if @sections[section].key?(key)
|
|
356
|
+
@sections[section][key].replace(newvalues)
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
return nil
|
|
360
|
+
end #replaceValues
|
|
361
|
+
|
|
362
|
+
#Return true if the key exists for the section "section"
|
|
363
|
+
#if global search is set to true, return true if the key exists in the root section and not in the section itself
|
|
364
|
+
#Parameters:
|
|
365
|
+
# key : string, the key to search
|
|
366
|
+
# section: string, the section where to search the key (default the root one)
|
|
367
|
+
# globalSearch: boolean, if the section is not the root one, return true if the key is found in the root section even if it not exists in the given section
|
|
368
|
+
def keyExists?(key, section, globalSearch=false)
|
|
369
|
+
return false if @sections.empty?
|
|
370
|
+
if ( section == nil)
|
|
371
|
+
return false unless @sections.has_key?(@@rootsection)
|
|
372
|
+
return @sections[@@rootsection].has_key?(key)
|
|
373
|
+
else
|
|
374
|
+
return false unless @sections.has_key?(section)
|
|
375
|
+
if (globalSearch == true and @sections.has_key?(@@rootsection))
|
|
376
|
+
return ( @sections[section].has_key?(key) || @sections[@@rootsection].has_key?(key) )
|
|
377
|
+
else
|
|
378
|
+
return @sections[section].has_key?(key)
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
#Return true if the specific section is found
|
|
384
|
+
def sectionExists? (section)
|
|
385
|
+
return false if section == nil
|
|
386
|
+
return false if @sections.empty?
|
|
387
|
+
return @sections.has_key?(section)
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
#Return true if at list one key is present
|
|
391
|
+
def haveKeys? (section=@@rootsection)
|
|
392
|
+
return false if @sections.empty?
|
|
393
|
+
return true unless @sections[section].empty?
|
|
394
|
+
return false
|
|
395
|
+
end #haveKeys?
|
|
396
|
+
|
|
397
|
+
#Return true if at list one section is present
|
|
398
|
+
def haveSections? ()
|
|
399
|
+
return true unless self.getSections().empty?
|
|
400
|
+
return false
|
|
401
|
+
end #haveSections?
|
|
402
|
+
|
|
403
|
+
#Return false if at list one key is found, whatever its section, global or not
|
|
404
|
+
def isEmpty?()
|
|
405
|
+
return false if self.haveKeys?
|
|
406
|
+
if self.haveSections?
|
|
407
|
+
self.getSections().each do |section|
|
|
408
|
+
return false if self.haveKeys?(section)
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
return true
|
|
412
|
+
end #isEmpty?()
|
|
413
|
+
|
|
414
|
+
#Return the root section name (for loops with sections?)
|
|
415
|
+
def getRootSectionName
|
|
416
|
+
return @@rootsection
|
|
417
|
+
end
|
|
418
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env rspec
|
|
2
|
+
###############################################################################
|
|
3
|
+
## Author: Erwan SEITE
|
|
4
|
+
## Aim: Read or Write config files written in Unix Style
|
|
5
|
+
## Licence : GPL v2
|
|
6
|
+
## Source : https://github.com/wanix/ruby-UnixConfigStyle
|
|
7
|
+
## Help : http://betterspecs.org/fr/
|
|
8
|
+
###############################################################################
|
|
9
|
+
require 'rspec'
|
|
10
|
+
$: << File.join(File.dirname(__FILE__), "..", "lib")
|
|
11
|
+
require 'unixconfigstyle.rb'
|
|
12
|
+
|
|
13
|
+
describe 'ruby-UnixConfigStyle' do
|
|
14
|
+
|
|
15
|
+
unix_config_file1=File.dirname(__FILE__)+"/configfiles/conf_unix1.cfg"
|
|
16
|
+
context "The file "+unix_config_file1+" should be parsed" do
|
|
17
|
+
it "Should give you an array of sections (Section1, Section2, newsection)" do
|
|
18
|
+
objUnixConfFile1 = UnixConfigStyle.new(unix_config_file1)
|
|
19
|
+
objUnixConfFile1.getSections().should eq(["Section1","Section2","newsection"])
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: unixconfigstyle
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Erwan SEITE
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2014-05-15 00:00:00.000000000 Z
|
|
13
|
+
dependencies: []
|
|
14
|
+
description: ! " This library manage config file written in Unix style\n Can manage
|
|
15
|
+
multi-values, concat multiple files, use it as a config object (see easyfpm)\n"
|
|
16
|
+
email: wanix.fr@gmail.com
|
|
17
|
+
executables: []
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- lib/unixconfigstyle.rb
|
|
22
|
+
- tests/test-unixconfigstyle.rb
|
|
23
|
+
homepage: https://github.com/wanix/ruby-UnixConfigStyle
|
|
24
|
+
licenses:
|
|
25
|
+
- GPLv2
|
|
26
|
+
post_install_message:
|
|
27
|
+
rdoc_options: []
|
|
28
|
+
require_paths:
|
|
29
|
+
- lib
|
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
31
|
+
none: false
|
|
32
|
+
requirements:
|
|
33
|
+
- - ! '>='
|
|
34
|
+
- !ruby/object:Gem::Version
|
|
35
|
+
version: 1.8.7
|
|
36
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
37
|
+
none: false
|
|
38
|
+
requirements:
|
|
39
|
+
- - ! '>='
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '0'
|
|
42
|
+
requirements: []
|
|
43
|
+
rubyforge_project:
|
|
44
|
+
rubygems_version: 1.8.23
|
|
45
|
+
signing_key:
|
|
46
|
+
specification_version: 3
|
|
47
|
+
summary: Parse, Write and manage config files in Unix Format
|
|
48
|
+
test_files:
|
|
49
|
+
- tests/test-unixconfigstyle.rb
|