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