rubyyabt 0.0.5 → 0.1.6
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/bin/rubyyabt-backup.rb +1 -0
- data/classes/Backup.rb +8 -8
- data/classes/Chunk.rb +4 -16
- data/classes/ProxyHTTP.rb +6 -18
- data/classes/SMGFile.rb +8 -23
- data/classes/Target.rb +5 -6
- data/classes/cui.rb +40 -23
- metadata +3 -3
data/bin/rubyyabt-backup.rb
CHANGED
@@ -36,6 +36,7 @@ OptionParser.new do |opts|
|
|
36
36
|
opts.on("-g", "--gpg-key KEY", "Use KEY as GPG key for encryption and signing") { |v| options[:gpg_key] = v }
|
37
37
|
opts.on("-h", "--gpg-pass PASS", "Password for GPG key") { |v| options[:gpg_pass] = v }
|
38
38
|
opts.on("-H", "--gpg-passfile FILE", "Read password for GPG key from FILE") { |v| options[:gpg_pass] = File.read(v) }
|
39
|
+
opts.on("-l", "--log-file FILE", "Write log to FILE") { |v| options[:logfile] = v.to_s }
|
39
40
|
opts.on("-c", "--cache-max-age DAYS", "Allow maximum of DAYS time for a positive cache hit. False hits are never cached.") { |v| options[:cache_max_age] = v.to_i *(24*60*60) }
|
40
41
|
opts.on("", "--http-timeout SECS", "Require all http requests to complete within SECS seconds.") { |v| options[:http_timeout] = v.to_i }
|
41
42
|
opts.on("-C", "--empty-cache", "Start with an empty cache instead of restoring the cache from saved data") { options[:empty_cache] = true }
|
data/classes/Backup.rb
CHANGED
@@ -32,20 +32,20 @@ class Backup
|
|
32
32
|
@time = Time.now
|
33
33
|
@time.utc
|
34
34
|
@name = @time.strftime("%Y%m%dT%H%M%S") unless @name
|
35
|
-
@cui.message("Initialized backup #{@name}")
|
35
|
+
@cui.message("Initialized backup #{@name}", true, true)
|
36
36
|
end
|
37
37
|
|
38
38
|
def backup!()
|
39
39
|
$errors = 0 if not $errors
|
40
|
-
@cui.message("Scanning for files...")
|
40
|
+
@cui.message("Scanning for files...", true, true)
|
41
41
|
@cui.start
|
42
|
-
@cui.message("Found #{@source.files.count.to_s} files and directories")
|
42
|
+
@cui.message("Found #{@source.files.count.to_s} files and directories", true, true)
|
43
43
|
backup_meta = Array.new
|
44
44
|
backup_meta << '[Backup]'
|
45
45
|
cache_timer = Time.now
|
46
46
|
@source.files.each { | f |
|
47
47
|
if (Time.now - cache_timer) > 900 then
|
48
|
-
@cui.message("Uploading cache data...")
|
48
|
+
@cui.message("Uploading cache data...", true, true)
|
49
49
|
@target.upload_cache
|
50
50
|
cache_timer = Time.now
|
51
51
|
end
|
@@ -65,19 +65,19 @@ class Backup
|
|
65
65
|
$errors += 1
|
66
66
|
end
|
67
67
|
}
|
68
|
-
@cui.message("Waiting for last chunk to finish uploading...")
|
68
|
+
@cui.message("Waiting for last chunk to finish uploading...", true, true)
|
69
69
|
@cui.error("DEBUG[#{Thread.current.inspect}]: Joining chunk threads") if $myDEBUG
|
70
70
|
chunk = Chunk.new
|
71
71
|
chunk.join
|
72
72
|
@cui.stop
|
73
73
|
@cui.update
|
74
|
-
@cui.message("Finished backing up data. Now uploading metadata for backup #{@name}.")
|
74
|
+
@cui.message("Finished backing up data. Now uploading metadata for backup #{@name}.", true, true)
|
75
75
|
backup_meta = backup_meta.join("\n")
|
76
76
|
@cui.error("DEBUG[#{Thread.current.inspect}]: Writing backup info") if $myDEBUG
|
77
77
|
@target.write(:backup, @name, backup_meta)
|
78
|
-
@cui.message("Uploading cache data...")
|
78
|
+
@cui.message("Uploading cache data...", true, true)
|
79
79
|
@target.upload_cache
|
80
|
-
@cui.error("Errors: A total of #{$errors} errors have been encountered.") if $errors > 0
|
80
|
+
@cui.error("Errors: A total of #{$errors} errors have been encountered.", true, true) if $errors > 0
|
81
81
|
return $errors
|
82
82
|
end
|
83
83
|
|
data/classes/Chunk.rb
CHANGED
@@ -10,8 +10,6 @@ require 'classes/Target'
|
|
10
10
|
#noinspection RubyResolve
|
11
11
|
require 'classes/cui'
|
12
12
|
|
13
|
-
$myDEBUG = false unless $myDEBUG
|
14
|
-
|
15
13
|
class Chunk
|
16
14
|
attr_reader :data, :length
|
17
15
|
@@upload_mutex = Mutex.new
|
@@ -27,16 +25,12 @@ class Chunk
|
|
27
25
|
end
|
28
26
|
|
29
27
|
def join()
|
30
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Joining chunk thread") if $myDEBUG
|
31
28
|
@@upload_thread.join if @@upload_thread
|
32
29
|
end
|
33
30
|
|
34
31
|
def set_data(data)
|
35
|
-
@cui.error("DEBUG[#{Thread.current.inspect}: Entered chunk set_data") if $myDEBUG
|
36
32
|
@data = data
|
37
|
-
@cui.error("DEBUG[#{Thread.current.inspect}: Set data") if $myDEBUG
|
38
33
|
@length = @data.length
|
39
|
-
@cui.error("DEBUG[#{Thread.current.inspect}: Calculated length") if $myDEBUG
|
40
34
|
@md5 = nil
|
41
35
|
@md5 = Digest::MD5.hexdigest(@data)
|
42
36
|
@sha256 = nil
|
@@ -64,26 +58,20 @@ class Chunk
|
|
64
58
|
end
|
65
59
|
|
66
60
|
def backup!()
|
67
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Locking chunk upload mutex in thread #{Thread.current.inspect}") if $myDEBUG
|
68
61
|
@@upload_mutex.synchronize {
|
69
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Got lock of chunk upload mutex in thread #{Thread.current.inspect}") if $myDEBUG
|
70
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Trying to join earlier upload threads if any (@@uploadThread: #{@@upload_thread.inspect})") if $myDEBUG
|
71
62
|
@@upload_thread.join if @@upload_thread
|
72
63
|
@@upload_thread = Thread.new {
|
73
64
|
target = Target.instance # Get a target object, then ...
|
74
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Checking if target chunk exists (#{sha256}, #{md5})") if $myDEBUG
|
75
65
|
if not target.exists?(:chunk, "#{sha256}.#{md5}") then
|
76
|
-
@cui.error("Uploading chunk #{sha256}.#{md5}...") if $myDEBUG
|
77
66
|
target.write(:chunk, "#{sha256}.#{md5}", @data)
|
67
|
+
@cui.message("Chunk #{sha256}.#{md5} (#{@data.length} bytes) uploaded.", true, false)
|
78
68
|
end
|
79
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Upload chunk thread finished (thread id: #{Thread.current.inspect})") if $myDEBUG
|
80
69
|
}
|
81
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: New upload thread: @@upload_thread = #{@@upload_thread.inspect}") if $myDEBUG
|
82
70
|
}
|
83
71
|
end
|
84
72
|
|
85
73
|
def restore!()
|
86
|
-
@cui.message("Downloading chunk #{sha256}.#{md5}...")
|
74
|
+
@cui.message("Downloading chunk #{sha256}.#{md5}...", true, true)
|
87
75
|
target = Target.instance
|
88
76
|
@data = target.read(:chunk, "#{sha256}.#{md5}")
|
89
77
|
@length = @data.length
|
@@ -92,9 +80,9 @@ class Chunk
|
|
92
80
|
@md5 = nil
|
93
81
|
@sha256 = nil
|
94
82
|
if (expected_md5 == md5) and (expected_sha256 == sha256) then
|
95
|
-
@cui.message("
|
83
|
+
@cui.message("Chunk verified", true, true)
|
96
84
|
else
|
97
|
-
@cui.
|
85
|
+
@cui.error("checksum error in chunk #{sha256}.#{md5}", true, true)
|
98
86
|
raise 'checksum error'
|
99
87
|
end
|
100
88
|
end
|
data/classes/ProxyHTTP.rb
CHANGED
@@ -8,8 +8,6 @@ require 'thread'
|
|
8
8
|
#noinspection RubyResolve
|
9
9
|
require 'classes/proxy_http_cache_hash'
|
10
10
|
|
11
|
-
$myDEBUG = false if not $myDEBUG
|
12
|
-
$myVERBOSE = false if not $myVERBOSE
|
13
11
|
$options = nil unless $options
|
14
12
|
|
15
13
|
class ProxyHTTP
|
@@ -60,48 +58,43 @@ class ProxyHTTP
|
|
60
58
|
@cui.error("Cache is not compatible. Starting with an empty cache.")
|
61
59
|
@cache = ProxyHTTPCache_Hash.new
|
62
60
|
end
|
61
|
+
@cui.message("Successfully restored cache with a size of #{cache_data.length} bytes.", true, true)
|
63
62
|
rescue Exception # Just start out with an empty cache
|
64
63
|
@cache = ProxyHTTPCache_Hash.new
|
64
|
+
@cui.message("Unable to restore cache. Starting with an empty cache.", true, true)
|
65
65
|
end
|
66
66
|
|
67
67
|
end
|
68
68
|
|
69
69
|
#noinspection RubyScope
|
70
70
|
def request(http_request, timeout = 300, tries = 20)
|
71
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Trying to lock ProxyHTTP request mutex in thread #{Thread.current.inspect}") if $myDEBUG
|
72
71
|
@mutex.synchronize {
|
73
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Got ProxyHTTP request mutex in thread #{Thread.current.inspect}") if $myDEBUG
|
74
72
|
response = ''
|
75
73
|
while tries > 0 do
|
76
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Got #{tries} tries left for request #{http_request.inspect} #{http_request.path}, timeout #{timeout}") if $myDEBUG
|
77
74
|
begin
|
78
75
|
Timeout::timeout(timeout) {
|
79
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Sending request #{http_request.inspect} for #{http_request.path}....") if $myDEBUG
|
80
76
|
response = @http.request(http_request)
|
81
77
|
}
|
82
78
|
rescue Timeout::Error
|
83
79
|
tries -= 1
|
84
|
-
@cui.error("Timeout during request. #{tries} tries left")
|
80
|
+
@cui.error("Timeout during request. #{tries} tries left", true, true)
|
85
81
|
retry if tries > 0
|
86
82
|
raise
|
87
83
|
rescue Exception => ex
|
88
|
-
@cui.error("Caught exception #{ex} with message #{ex.message} during request. #{tries} tries left"
|
84
|
+
@cui.error("Caught exception #{ex} with message #{ex.message} during request. #{tries} tries left", true, false)
|
89
85
|
tries -= 1
|
90
86
|
retry if tries > 0
|
91
87
|
raise
|
92
88
|
end
|
93
89
|
code = response.code.to_i
|
94
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Response code: #{code}") if $myDEBUG
|
95
90
|
return response if (code >= 200) and (code < 300)
|
96
91
|
if (code >= 400) and (code < 500) # No retries for these errors...
|
97
92
|
# Yeehaw! we need an exception for code 401 since humyo sometimes replies with it with correct authorization
|
98
93
|
tries = 0 if (code != 401)
|
99
94
|
end
|
100
95
|
tries -= 1
|
101
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: #{tries} tries left for this request. Retrying after sleep if > 0") if $myDEBUG
|
102
96
|
sleep(rand) if tries > 0 # Sleep up to one second before retrying
|
103
97
|
end
|
104
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Raising exception for failed request: #{response.code} #{response.message}") if $myDEBUG
|
105
98
|
raise 'HTTP request failed: ' + response.code + ' ' + response.message
|
106
99
|
}
|
107
100
|
end
|
@@ -118,7 +111,6 @@ class ProxyHTTP
|
|
118
111
|
get = Net::HTTP::Get.new(uri.request_uri)
|
119
112
|
get.initialize_http_header({"User-Agent" => $options[:user_agent]})
|
120
113
|
get.basic_auth($options[:username], $options[:password])
|
121
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Reading from #{uri.to_s}") if $myDEBUG
|
122
114
|
begin
|
123
115
|
response = request(get, $options[:http_timeout])
|
124
116
|
rescue Exception => ex
|
@@ -142,22 +134,19 @@ class ProxyHTTP
|
|
142
134
|
put.initialize_http_header({"User-Agent" => $options[:user_agent], "Content-Type" => "application/octet-stream"})
|
143
135
|
put.basic_auth($options[:username], $options[:password])
|
144
136
|
put.body = data
|
145
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Writing to #{uri.to_s}") if $myDEBUG
|
146
137
|
begin
|
147
138
|
response = request(put, 180)
|
148
139
|
rescue RuntimeError => ex
|
149
140
|
if ex.message == "HTTP request failed: 409 Conflict" then
|
150
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Caught a 409 Conflict error") if $myDEBUG
|
151
141
|
if (subdir_type != type) then
|
152
142
|
begin
|
153
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Trying to create the directory #{@url.merge(@types[type] + '/').to_s}") if $myDEBUG
|
154
143
|
mkdir(@url.merge(@types[type] + '/'))
|
155
144
|
rescue RuntimeError => rt
|
156
145
|
@cui.error("DEBUG[#{Thread.current.inspect}]: Caught exception during mkdir: #{rt.message}") if $myDEBUG
|
157
146
|
raise if rt.message[0..23] != "HTTP request failed: 405"
|
158
147
|
end
|
159
148
|
end
|
160
|
-
@cui.
|
149
|
+
@cui.message("Trying to create the directory #{@url.merge(@types[type] + '/').merge(subdir).to_s}", true, false)
|
161
150
|
mkdir(@url.merge(@types[type] + '/').merge(subdir))
|
162
151
|
end
|
163
152
|
retry
|
@@ -166,7 +155,6 @@ class ProxyHTTP
|
|
166
155
|
raise
|
167
156
|
else
|
168
157
|
@cache.add(type, file) if @@valid_caches.include?(type)
|
169
|
-
@cui.error("DEBUG[#{Thread.current.inspect}]: Added #{file} to cache list for #{subdir_type}") if $myDEBUG
|
170
158
|
return true
|
171
159
|
end
|
172
160
|
end
|
@@ -175,7 +163,7 @@ class ProxyHTTP
|
|
175
163
|
mkcol = Net::HTTP::Mkcol.new(uri.request_uri)
|
176
164
|
mkcol.initialize_http_header({"User-Agent" => $options[:user_agent]})
|
177
165
|
mkcol.basic_auth($options[:username], $options[:password])
|
178
|
-
@cui.
|
166
|
+
@cui.message("Trying to create directory #{uri.to_s}", true, false)
|
179
167
|
begin
|
180
168
|
request(mkcol)
|
181
169
|
rescue Exception => ex
|
data/classes/SMGFile.rb
CHANGED
@@ -11,8 +11,6 @@ require 'digest/md5'
|
|
11
11
|
require 'digest/sha2'
|
12
12
|
require 'time'
|
13
13
|
|
14
|
-
$myDEBUG = false if not $myDEBUG
|
15
|
-
$myVERBOSE = false if not $myVERBOSE
|
16
14
|
$options = nil unless $options
|
17
15
|
|
18
16
|
class SMGFile
|
@@ -69,33 +67,23 @@ class SMGFile
|
|
69
67
|
size = 0
|
70
68
|
md5hashing = Digest::MD5.new
|
71
69
|
sha256hashing = Digest::SHA2.new(256)
|
72
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: Created hashing objects") if $myDEBUG
|
73
70
|
chunks = ''
|
71
|
+
gc_counter = -1 # Initialize a counter for the garbage collection
|
74
72
|
while !fd.eof?
|
75
|
-
|
73
|
+
GC.start if ((gc_counter += 1) % 30) == 0 # Run the garbage collection every now and then
|
76
74
|
chunk = Chunk.new
|
77
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: Created new chunk") if $myDEBUG
|
78
75
|
data = fd.read($options[:chunk_size])
|
79
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: Read data") if $myDEBUG
|
80
76
|
chunk.set_data(data)
|
81
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: Saved data in chunk") if $myDEBUG
|
82
77
|
md5hashing << data
|
83
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: hashed for MD5") if $myDEBUG
|
84
78
|
sha256hashing << data
|
85
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: hashed for sha256") if $myDEBUG
|
86
79
|
size += data.length
|
87
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: Updated read size") if $myDEBUG
|
88
80
|
chunk.backup! # Upload this chunk
|
89
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: backed up chunk") if $myDEBUG
|
90
81
|
chunks += chunk.sha256 + '.' + chunk.md5 + "\n"
|
91
82
|
@cui.finished_size_add(data.length)
|
92
83
|
end
|
93
84
|
fd.close()
|
94
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: Closed FD") if $myDEBUG
|
95
85
|
md5 = md5hashing.hexdigest
|
96
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: Got MD5") if $myDEBUG
|
97
86
|
sha256 = sha256hashing.hexdigest
|
98
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: Got sha256") if $myDEBUG
|
99
87
|
# Build the metadata file
|
100
88
|
@metadata = "[stat]\n"
|
101
89
|
@metadata += "filename = " + @filename + "\n"
|
@@ -112,14 +100,12 @@ class SMGFile
|
|
112
100
|
@metadata += "\n"
|
113
101
|
@metadata += "[chunks]\n"
|
114
102
|
@metadata += chunks
|
115
|
-
@cui.message("Size mismatch: expected #{expected_size} but found #{size}!") if expected_size != size
|
103
|
+
@cui.message("Size mismatch: expected #{expected_size} but found #{size}!", true, true) if expected_size != size
|
116
104
|
@size = size
|
117
105
|
@mtime = mtime
|
118
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: Checking if file already exists on server") if $myDEBUG
|
119
106
|
return true if @target.exists?(:file, "#{meta_sha256}.#{meta_md5}") # if this chunk already exists, no need to upload it
|
120
|
-
@cui.message("Uploading file metadata #{@filename}: #{meta_sha256}.#{meta_md5}..."
|
107
|
+
@cui.message("Uploading file metadata #{@filename}: #{meta_sha256}.#{meta_md5}...", true, true)
|
121
108
|
@target.write(:file, "#{meta_sha256}.#{meta_md5}", @metadata)
|
122
|
-
@cui.message("DEBUG[#{Thread.current.inspect}: Uploaded file metadata") if $myDEBUG
|
123
109
|
end
|
124
110
|
|
125
111
|
def backup_dir()
|
@@ -141,12 +127,11 @@ class SMGFile
|
|
141
127
|
@size = 0
|
142
128
|
@mtime = mtime
|
143
129
|
return true if @target.exists?(:file, "#{meta_sha256}.#{meta_md5}") # if this chunk already exists, no need to upload it
|
144
|
-
@cui.message("Uploading directory metadata #{@filename}: #{meta_sha256}.#{meta_md5}..."
|
130
|
+
@cui.message("Uploading directory metadata #{@filename}: #{meta_sha256}.#{meta_md5}...", true, true)
|
145
131
|
@target.write(:file, "#{meta_sha256}.#{meta_md5}", @metadata)
|
146
132
|
end
|
147
133
|
|
148
134
|
def backup_link()
|
149
|
-
@cui.message("Backing up link #{@filename}") if $myVERBOSE
|
150
135
|
stat = @source.lstat(@filename)
|
151
136
|
ftype = stat.ftype
|
152
137
|
mtime = stat.mtime.utc.rfc2822
|
@@ -164,7 +149,7 @@ class SMGFile
|
|
164
149
|
@size = 0
|
165
150
|
@mtime = mtime
|
166
151
|
return true if @target.exists?(:file, "#{meta_sha256}.#{meta_md5}") # if this chunk already exists, no need to upload it
|
167
|
-
@cui.message("Uploading file metadata #{@filename}: #{meta_sha256}.#{meta_md5}..."
|
152
|
+
@cui.message("Uploading file metadata #{@filename}: #{meta_sha256}.#{meta_md5}...", true, true)
|
168
153
|
@target.write(:file, "#{meta_sha256}.#{meta_md5}", @metadata)
|
169
154
|
end
|
170
155
|
|
@@ -218,9 +203,9 @@ class SMGFile
|
|
218
203
|
md5 = md5hashing.hexdigest
|
219
204
|
sha256 = sha256hashing.hexdigest
|
220
205
|
if (@md5 = md5) and (@sha256 = sha256) then
|
221
|
-
@cui.message("File verified")
|
206
|
+
@cui.message("File verified", true, true)
|
222
207
|
else
|
223
|
-
@cui.error("Checksum error in file #{@filename}: #{sha256}.#{md5}")
|
208
|
+
@cui.error("Checksum error in file #{@filename}: #{sha256}.#{md5}", true, true)
|
224
209
|
end
|
225
210
|
end
|
226
211
|
|
data/classes/Target.rb
CHANGED
@@ -43,16 +43,15 @@ class Target
|
|
43
43
|
else
|
44
44
|
raise "No idea how to connect to #{$options[:target]}"
|
45
45
|
end
|
46
|
-
@cui.message("Initialized proxy as #{@proxy.class}."
|
46
|
+
@cui.message("Initialized proxy as #{@proxy.class}.", true, true)
|
47
47
|
begin
|
48
48
|
if @proxy.caching? then
|
49
49
|
if not $options[:empty_cache] then
|
50
|
-
@cui.message(
|
50
|
+
@cui.message('Trying to restore cache...', true, false)
|
51
51
|
compressed_cache_data = read(:cache, "flist")
|
52
52
|
begin
|
53
53
|
# Check if the data is compressed and uncompress the data
|
54
54
|
cache_data = Zlib::Inflate.inflate(compressed_cache_data)
|
55
|
-
@cui.message("Uncompressed cache data from #{compressed_cache_data.length} bytes to #{cache_data.length} bytes.")
|
56
55
|
rescue Exception
|
57
56
|
# Uncompress failed, so the data was probably uncompressed from the beginning.
|
58
57
|
cache_data = compressed_cache_data
|
@@ -102,15 +101,15 @@ class Target
|
|
102
101
|
rescue Exception
|
103
102
|
# Seems like compression does not work. We'll just use the uncompressed data then.
|
104
103
|
compressed_cache_data = cache_data
|
105
|
-
@cui.message('Unable to compress the cache data for upload. Using uncompressed data.')
|
104
|
+
@cui.message('Unable to compress the cache data for upload. Using uncompressed data.', true, false)
|
106
105
|
end
|
107
|
-
@cui.
|
106
|
+
@cui.message("Cache has a length of #{compressed_cache_data.length}. Uploading...", true, false)
|
108
107
|
write(:cache, 'flist', compressed_cache_data)
|
109
108
|
end
|
110
109
|
end
|
111
110
|
|
112
111
|
def export_key()
|
113
|
-
@cui.
|
112
|
+
@cui.message("Exporting keys...", true, true)
|
114
113
|
IO.popen('"' + $options[:gpg_bin] + '" ' + '--export-ownertrust', 'w+') do | gpg |
|
115
114
|
gpg.close_write()
|
116
115
|
trust = gpg.read()
|
data/classes/cui.rb
CHANGED
@@ -2,6 +2,7 @@ require 'singleton'
|
|
2
2
|
#noinspection RubyResolve
|
3
3
|
require 'thread'
|
4
4
|
|
5
|
+
$options = nil unless $options
|
5
6
|
|
6
7
|
# Usage of stdout and stderr:
|
7
8
|
# stdout will be used for normal status messages like the status bar.
|
@@ -29,6 +30,7 @@ class Cui
|
|
29
30
|
@changed = false
|
30
31
|
@active = false
|
31
32
|
@exists = true
|
33
|
+
@logfile = nil
|
32
34
|
end
|
33
35
|
def exists(e)
|
34
36
|
@exists = e
|
@@ -66,6 +68,7 @@ class Cui
|
|
66
68
|
@last_file_name = @current_file_name
|
67
69
|
@current_file_name = file.to_str
|
68
70
|
update
|
71
|
+
write_log("File: #{file.to_s} (#{@finished_files + 1}/#{@total_files}; #{(@finished_size/1024/1024).to_i.to_s} MB/#{(@total_size/1024/1024).to_i.to_s} MB)")
|
69
72
|
}
|
70
73
|
end
|
71
74
|
def start()
|
@@ -108,34 +111,40 @@ class Cui
|
|
108
111
|
$stdout.print(backspace + line)
|
109
112
|
@changed = false
|
110
113
|
end
|
111
|
-
def message(text)
|
114
|
+
def message(text, logging = false, write_stdout = true)
|
112
115
|
@mutex.synchronize {
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
116
|
+
write_log(text) if logging
|
117
|
+
if write_stdout then
|
118
|
+
case @active
|
119
|
+
when true
|
120
|
+
backspace = ("\b" * @last_length)
|
121
|
+
text += " " * (@last_length - text.length) if (@last_length - text.length) > 0
|
122
|
+
@last_length = 0
|
123
|
+
$stdout.print(backspace + text + "\n")
|
124
|
+
update
|
125
|
+
when false
|
126
|
+
# If there's no regular update, we can just write out a new line
|
127
|
+
$stdout.print("\n" + text + "\n")
|
128
|
+
end
|
123
129
|
end
|
124
130
|
}
|
125
131
|
end
|
126
|
-
def error(text)
|
132
|
+
def error(text, logging = true, write_stderr = true)
|
127
133
|
@mutex.synchronize {
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
134
|
+
write_log(text) if logging
|
135
|
+
if write_stderr then
|
136
|
+
case @active
|
137
|
+
when true
|
138
|
+
backspace = ("\b" * @last_length) # Calculate the amount of backspaces required
|
139
|
+
spaces = ""
|
140
|
+
spaces = " " * (@last_length - text.length) if (@last_length - text.length) > 0
|
141
|
+
$stderr.print(backspace + text + spaces + "\n")
|
142
|
+
@last_length = 0
|
143
|
+
update
|
144
|
+
when false
|
145
|
+
# If there's no regular update, we can just write out a new line
|
146
|
+
$stdout.print("\n" + text + "\n")
|
147
|
+
end
|
139
148
|
end
|
140
149
|
}
|
141
150
|
end
|
@@ -145,4 +154,12 @@ class Cui
|
|
145
154
|
@update_thread.join
|
146
155
|
@update_thread = nil
|
147
156
|
end
|
157
|
+
def write_log(text)
|
158
|
+
return if $options[:logfile].nil?
|
159
|
+
@logfile = File.new($options[:logfile], "w:utf-8") if @logfile.nil?
|
160
|
+
date_time = Time.now.strftime('%Y-%m-%d %H:%M:%S')
|
161
|
+
text = date_time + " " + text + "\n"
|
162
|
+
@logfile.write(text)
|
163
|
+
@logfile.flush
|
164
|
+
end
|
148
165
|
end
|