1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
#!/usr/bin/env ruby
#-- vim:sw=2:et
#++
#
# :title: Registry import/export and migration.
#
# You can use this script to,
# - backup the rbot registry in a format that is platform independent
# - restore backups
# - migrate old rbot registries bdb (ruby 1.8) and tokyocabinet.
#
# Author:: apoc (Matthias Hecker) <apoc@geekosphere.org>
# Copyright:: (C) 2014 Matthias Hecker
# License:: GPLv3
begin; require 'rubygems'; rescue Exception; puts "[#{$!}]"; end
begin; require 'dbm'; rescue Exception; puts "[#{$!}]"; end
begin; require 'bdb'; rescue Exception; puts "[#{$!}]"; end
begin; require 'tokyocabinet'; rescue Exception; puts "[#{$!}]"; end
puts 'RBot registry backup/import script.'
puts 'Ruby: %s | DBM: %s | BDB: %s | TC: %s' % [RUBY_VERSION,
(DBM::VERSION rescue '-'),
(BDB::VERSION rescue '-'),
(TokyoCabinet::VERSION rescue '-')]
if ARGV.length > 3 or ARGV.length < 2
puts """
Usage rbotdb [backup|restore] <BACKUP/RESTORE-FILE> [<PROFILE>]
Examples:
rbotdb backup ~/rbot_db_backup.yaml
rbotdb backup ~/rbot_db_backup.yaml.gz ~/.rbot_two
rbotdb restore ~/rbot_db_backup.yaml
"""
exit
end
mode = ARGV[0] if %w{backup restore}.include? ARGV[0]
file = File.expand_path ARGV[1]
profile = File.expand_path(ARGV[2] ? ARGV[2] : '~/.rbot')
$last_error = ''
class Backup
class RegistryFile
def initialize(registry, path)
@registry = registry
@path = path
end
def path
@path
end
def abs
File.expand_path(File.join(@registry, @path))
end
def ext
File.extname(@path)
end
def valid?
File.file?(abs) and %w{.db .tdb}.include? ext
end
end
def initialize(profile)
@profile = profile
@registry = File.join(profile, './registry')
end
# list all database files:
def list
return nil if not File.directory? @registry
Dir.chdir @registry
Dir.glob(File.join('**', '*')).map do |name|
RegistryFile.new(@registry, name)
end
end
def load(ext='.db')
@data = {}
list.each do |file|
next unless file.ext == ext
db = loadDBM(file)
db = loadBDB(file) if not db
db = loadTC(file) if not db
if not db
puts 'ERROR: unable to load db: %s, last error: %s' % [file.abs, $last_error]
else
puts 'Loaded: %s [%d values]' % [file.abs, db.length]
@data[file.path] = db
end
end
end
def write(file)
File.open(file, 'w') do |f|
f.write(Marshal.dump(@data))
end
end
private
def loadDBM(file)
path = file.abs
begin
dbm = DBM.open(path.gsub(/\.[^\.]+$/,''), 0666, DBM::READER)
data = dbm.to_hash
dbm.close
rescue
$last_error = "[%s]\n%s" % [$!, $@.join("\n")]
end
data
end
def loadBDB(file)
path = file.abs
begin
db = BDB::Hash.open(path, nil, 'r')
data = {}
db.each do |key, value|
data[key] = value
end
db.close
rescue
$last_error = "[%s]\n%s" % [$!, $@.join("\n")]
end
data
end
def loadTC(file)
path = file.abs
begin
db = TokyoCabinet::BDB.new
db.open(path, TokyoCabinet::BDB::OREADER)
data = {}
db.each do |key, value|
data[key] = value
end
db.close
rescue
$last_error = "[%s]\n%s" % [$!, $@.join("\n")]
end
data
end
end
puts 'mode = ' + mode
puts 'profile= ' + profile
puts 'file = ' + file
if mode == 'backup'
backup = Backup.new(profile)
if File.exists? file
puts 'ERROR! Backup file already exists!'
exit
end
backup.load '.tdb'
backup.write(file)
else
registry = File.join(profile, './registry')
data = Marshal.load File.read(file)
data.each_pair do |path, db|
path = File.expand_path(File.join(registry, path))
# create directories:
dirs = File.dirname(path).split("/")
dirs.length.times { |i|
dir = dirs[0,i+1].join("/")+"/"
unless File.exist?(dir)
puts 'create subdir:'+dir
Dir.mkdir(dir)
end
}
path.gsub!(/\.([^\.]+)$/,'')
if File.exists? path+'.db' or File.exists? path+'.tdb'
raise 'error, unable to restore to existing db'
end
puts 'restore to: '+path
dbm = DBM.open(path, 0666, DBM::WRCREAT)
db.each_pair do |key, value|
dbm[key] = value
end
dbm.close
end
end
|