dotcfg 0.0.1.1
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/dotcfg.rb +138 -0
- data/rakefile.rb +13 -0
- metadata +47 -0
data/lib/dotcfg.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
# uses JSON or YAML for serialization
|
5
|
+
# top-level structure is object/hash/dict
|
6
|
+
#
|
7
|
+
# provide and prefer method-based access to str/sym/etc keys
|
8
|
+
# e.g.
|
9
|
+
# d = DotCfg.new('~/.dotcfg')
|
10
|
+
# d.hello = 'world'
|
11
|
+
# d.hello
|
12
|
+
# => "world"
|
13
|
+
# d.save
|
14
|
+
# d.get = "bent"
|
15
|
+
# d.load
|
16
|
+
# d.get
|
17
|
+
# => nil
|
18
|
+
#
|
19
|
+
class DotCfg
|
20
|
+
def self.normalize key
|
21
|
+
case key
|
22
|
+
when Numeric, Symbol
|
23
|
+
key
|
24
|
+
when String
|
25
|
+
# leading numerics are invalid
|
26
|
+
raise "invalid key: #{key}" if key[0,1] == '0' or key[0,1].to_i != 0
|
27
|
+
key.downcase.gsub(/\W/, '_').to_sym
|
28
|
+
else
|
29
|
+
raise "invalid key: #{key} (#{key.class})"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
DEFAULT = {}
|
34
|
+
|
35
|
+
PROCS = {
|
36
|
+
json: {
|
37
|
+
to: proc { |data| data.to_json },
|
38
|
+
from: proc { |json| YAML.load json },
|
39
|
+
pretty: proc { |data| JSON.pretty_generate data },
|
40
|
+
},
|
41
|
+
yaml: {
|
42
|
+
to: proc { |data| data.to_yaml },
|
43
|
+
from: proc { |yaml| YAML.load yaml },
|
44
|
+
pretty: proc { |data| data.to_yaml },
|
45
|
+
},
|
46
|
+
}
|
47
|
+
|
48
|
+
attr_reader :filename, :format, :storage
|
49
|
+
|
50
|
+
def initialize filename, format = :json
|
51
|
+
@filename = File.expand_path filename
|
52
|
+
@format = format
|
53
|
+
File.exists?(@filename) ? self.load : self.reset
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
# manipulate @storage
|
58
|
+
#
|
59
|
+
def [] key
|
60
|
+
key = self.class.normalize key
|
61
|
+
@storage[key] or @storage[key.to_s]
|
62
|
+
end
|
63
|
+
#
|
64
|
+
def []= key, value
|
65
|
+
@storage[self.class.normalize(key)] = value
|
66
|
+
end
|
67
|
+
#
|
68
|
+
def delete key
|
69
|
+
@storage.delete(self.class.normalize(key))
|
70
|
+
end
|
71
|
+
#
|
72
|
+
def method_missing key, *args
|
73
|
+
if key[-1,1] == '='
|
74
|
+
self[key[0, key.length - 1]] = args.first
|
75
|
+
else
|
76
|
+
self[key]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
#
|
80
|
+
def respond_to? key, *args
|
81
|
+
true
|
82
|
+
end
|
83
|
+
#
|
84
|
+
# end simple @storage manipulation
|
85
|
+
|
86
|
+
|
87
|
+
# serialization, based on PROCS
|
88
|
+
#
|
89
|
+
def serialize
|
90
|
+
raise "invalid storage" unless @storage.is_a? Hash
|
91
|
+
self.class::PROCS.fetch(@format)[:to].call @storage
|
92
|
+
end
|
93
|
+
#
|
94
|
+
def deserialize junk
|
95
|
+
data = self.class::PROCS.fetch(@format)[:from].call junk
|
96
|
+
raise "invalid junk: #{junk} (#{junk.class})" unless data.is_a? Hash
|
97
|
+
data.each { |k, v| self[k] = v }
|
98
|
+
@storage
|
99
|
+
end
|
100
|
+
#
|
101
|
+
def dump
|
102
|
+
self.class::PROCS.fetch(@format)[:pretty].call @storage
|
103
|
+
end
|
104
|
+
#
|
105
|
+
# end serialization
|
106
|
+
|
107
|
+
|
108
|
+
# file operations
|
109
|
+
#
|
110
|
+
def save
|
111
|
+
File.open(@filename, 'w') { |f| f.write self.serialize }
|
112
|
+
end
|
113
|
+
#
|
114
|
+
def load
|
115
|
+
rescues = 0
|
116
|
+
begin
|
117
|
+
File.open(@filename, 'r') { |f| @storage = self.deserialize f.read }
|
118
|
+
rescue Exception => e
|
119
|
+
rescues += 1
|
120
|
+
puts "#{e} (#{e.class})"
|
121
|
+
if rescues < 2
|
122
|
+
puts "Resetting #{@filename}"
|
123
|
+
reset
|
124
|
+
retry
|
125
|
+
end
|
126
|
+
puts "load failed!"
|
127
|
+
raise e
|
128
|
+
end
|
129
|
+
end
|
130
|
+
#
|
131
|
+
def reset
|
132
|
+
@storage = DEFAULT.dup
|
133
|
+
save
|
134
|
+
end
|
135
|
+
#
|
136
|
+
# end file operations
|
137
|
+
|
138
|
+
end
|
data/rakefile.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'buildar'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Buildar.new do |b|
|
5
|
+
b.use_git = true
|
6
|
+
b.version_file = 'VERSION'
|
7
|
+
b.gemspec.name = 'dotcfg'
|
8
|
+
b.gemspec.summary = 'simple filesystem de/serialization for app configs'
|
9
|
+
b.gemspec.author = 'Rick Hull'
|
10
|
+
b.gemspec.license = 'MIT'
|
11
|
+
b.gemspec.description = 'JSON and YAML config serialization and synch'
|
12
|
+
b.gemspec.files = %w{rakefile.rb lib/dotcfg.rb}
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dotcfg
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rick Hull
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-19 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: JSON and YAML config serialization and synch
|
15
|
+
email:
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- rakefile.rb
|
21
|
+
- lib/dotcfg.rb
|
22
|
+
homepage:
|
23
|
+
licenses:
|
24
|
+
- MIT
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
requirements: []
|
42
|
+
rubyforge_project:
|
43
|
+
rubygems_version: 1.8.23
|
44
|
+
signing_key:
|
45
|
+
specification_version: 3
|
46
|
+
summary: simple filesystem de/serialization for app configs
|
47
|
+
test_files: []
|