restic-service 0.2.2 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 20d2e8bcf01431f060bd3bf7873017742400d672
4
- data.tar.gz: da02e19bdb412eb16fdd109c4af7dc2bc7ae23c6
3
+ metadata.gz: fc0cdefcecb418357241e0acc940dc84572263d8
4
+ data.tar.gz: 9b3bf2bc152405e6fd8d4ffd4e950f8176b34a7f
5
5
  SHA512:
6
- metadata.gz: f772fd3950f54eda022a99db6b46a07f8fb8ee5ffb2095b312f30a6fb85111b1bb0cef9afca36e82d7d60704f8e517cc23daf2c6e12baa340a199b8cd55e1428
7
- data.tar.gz: edb746be5a8aff2b7c18fd90b97aededccc4b82520c5cdddc8dd781ce696542c5a36c96661210131bb4934ddfaff406d9d4ba99307ec9e92c1cb3fe22876225c
6
+ metadata.gz: 58013743c7a6ebf256b6eddc6ade110c43245513fa78242cb151698538307388af6a95e3c36b46fc381d19219780cec4c1c8543d571757429a3f81671083ae00
7
+ data.tar.gz: bd65807a2ca4f8314b39cf4f4c1fd571693c9148bb6f70db19c75d2965526bc0b69a28c4449e468a77b7ddcfd733a26650275a0138553f205cc6f8776a27e69b
@@ -12,6 +12,14 @@ module Restic
12
12
  "https://github.com/restic/restic/releases/download/v#{RESTIC_RELEASE_VERSION}/restic_#{RESTIC_RELEASE_VERSION}_#{platform}.bz2"
13
13
  end
14
14
 
15
+ RCLONE_RELEASE_VERSION = "1.41"
16
+
17
+ def self.rclone_release_url(platform)
18
+ basename = "rclone-v#{RCLONE_RELEASE_VERSION}-#{platform}"
19
+ url = "https://github.com/ncw/rclone/releases/download/v#{RCLONE_RELEASE_VERSION}/#{basename}.zip"
20
+ [basename, url]
21
+ end
22
+
15
23
 
16
24
  def initialize(binary_path)
17
25
  @root = File.dirname(File.dirname(binary_path))
@@ -61,39 +69,72 @@ module Restic
61
69
  reader.close if reader && !reader.closed?
62
70
  end
63
71
 
64
- def update_restic(platform, target_path)
65
- release_url = self.class.restic_release_url(platform)
66
-
67
- release_binary = nil
68
- while !release_binary
69
- response = Net::HTTP.get_response(URI(release_url))
72
+ def download_file(temp_path, url)
73
+ binary = nil
74
+ while !binary
75
+ response = Net::HTTP.get_response(URI(url))
70
76
  case response
71
77
  when Net::HTTPSuccess
72
- release_binary = response.body
78
+ binary = response.body
73
79
  when Net::HTTPRedirection
74
- release_url = response['location']
80
+ url = response['location']
75
81
  else
76
- raise FailedUpdate, "failed to fetch restic at #{release_url}: #{response}"
82
+ raise FailedUpdate, "failed to fetch #{url}: #{response}"
77
83
  end
78
84
  end
79
85
 
86
+ File.open(temp_path, 'w') do |io|
87
+ io.write binary
88
+ end
89
+ end
90
+
91
+ def update_release_if_needed(target_path, temp_path)
92
+ if File.file?(target_path)
93
+ current = File.read(target_path)
94
+ new = File.read(temp_path)
95
+ return false if current == new
96
+ end
97
+
98
+ FileUtils.mv temp_path, target_path
99
+ FileUtils.chmod 0755, target_path
100
+ true
101
+ end
102
+
103
+ def update_restic(platform, target_path)
104
+ release_url = self.class.restic_release_url(platform)
105
+
80
106
  tmpdir = Dir.mktmpdir
81
107
  restic_path = File.join(tmpdir, "restic")
82
- File.open("#{restic_path}.bz2", 'w') do |io|
83
- io.write release_binary
84
- end
108
+ download_file("#{restic_path}.bz2", release_url)
85
109
 
86
110
  if !system("bzip2", "-d", "#{restic_path}.bz2")
87
111
  raise FailedUpdate, "failed to uncompress the restic release file"
88
112
  end
113
+ update_release_if_needed(target_path, restic_path)
114
+
115
+ ensure
116
+ FileUtils.rm_rf tmpdir if tmpdir
117
+ end
118
+
119
+ def update_rclone(platform, target_path)
120
+ basename, release_url = self.class.rclone_release_url(platform)
121
+
122
+ tmpdir = Dir.mktmpdir
123
+ tmppath = File.join(tmpdir, "rclone.zip")
124
+ download_file(tmppath, release_url)
125
+
126
+ if !system("unzip", tmppath, chdir: tmpdir, out: '/dev/null')
127
+ raise FailedUpdate, "failed to uncompress the rclone release file"
128
+ end
89
129
 
130
+ rclone_path = File.join(tmpdir, basename, 'rclone')
90
131
  if File.file?(target_path)
91
132
  current = File.read(target_path)
92
- new = File.read(restic_path)
133
+ new = File.read(rclone_path)
93
134
  return if current == new
94
135
  end
95
136
 
96
- FileUtils.mv restic_path, target_path
137
+ FileUtils.mv rclone_path, target_path
97
138
  FileUtils.chmod 0755, target_path
98
139
  true
99
140
 
@@ -67,6 +67,22 @@ module Restic
67
67
  target.forget
68
68
  end
69
69
  end
70
+
71
+ def auto_update_tool(conf, updater, name, version)
72
+ begin
73
+ path = conf.tool_path(name, only_if_present: false)
74
+ rescue ArgumentError
75
+ puts "cannot auto-update #{name}, provide an explicit path in the 'tools' section of the configuration first"
76
+ return
77
+ end
78
+
79
+ puts "attempting to auto-update #{name}"
80
+ if updater.send("update_#{name}", conf.send("#{name}_platform"), path)
81
+ puts "updated #{name} to version #{version}"
82
+ else
83
+ puts "restic was already up-to-date"
84
+ end
85
+ end
70
86
  end
71
87
 
72
88
  desc 'whereami', 'finds the available backup targets'
@@ -104,25 +120,16 @@ module Restic
104
120
  puts "updating restic-service disabled in configuration"
105
121
  end
106
122
 
107
- update_restic = conf.auto_update_restic?
108
- if update_restic
109
- begin
110
- restic_path = conf.tool_path('restic')
111
- rescue ArgumentError
112
- puts "cannot auto-update restic, provide an explicit path in the 'tools' section of the configuration first"
113
- update_restic = false
114
- end
123
+ if conf.auto_update_restic?
124
+ auto_update_tool(conf, updater, 'restic', AutoUpdate::RESTIC_RELEASE_VERSION)
115
125
  else
116
126
  puts "updating restic disabled in configuration"
117
127
  end
118
128
 
119
- if update_restic
120
- puts "attempting to auto-update restic"
121
- if updater.update_restic(conf.restic_platform, restic_path)
122
- puts "updated restic to version #{AutoUpdate::RESTIC_RELEASE_VERSION}"
123
- else
124
- puts "restic was already up-to-date"
125
- end
129
+ if conf.auto_update_rclone?
130
+ auto_update_tool(conf, updater, 'rclone', AutoUpdate::RCLONE_RELEASE_VERSION)
131
+ else
132
+ puts "updating rclone disabled in configuration"
126
133
  end
127
134
  end
128
135
 
@@ -202,16 +202,17 @@ module Restic
202
202
  # @param [String]
203
203
  # @return [Boolean]
204
204
  def tool_available?(tool_name)
205
- @tools.has_key?(tool_name)
205
+ _, available = @tools[tool_name]
206
+ available
206
207
  end
207
208
 
208
209
  # The full path of a given tool
209
210
  #
210
211
  # @param [String]
211
212
  # @return [Pathname]
212
- def tool_path(tool_name)
213
+ def tool_path(tool_name, only_if_present: true)
213
214
  if tool = @tools[tool_name]
214
- tool
215
+ tool[0] if tool[1] || !only_if_present
215
216
  else
216
217
  raise ArgumentError, "cound not find '#{tool_name}'"
217
218
  end
@@ -229,6 +230,14 @@ module Restic
229
230
  @auto_update_restic
230
231
  end
231
232
 
233
+ def auto_update_rclone?
234
+ @auto_update_rclone
235
+ end
236
+
237
+ def rclone_platform
238
+ @auto_update_rclone
239
+ end
240
+
232
241
  # Add the information stored in a YAML-like hash into this
233
242
  # configuration
234
243
  #
@@ -247,6 +256,8 @@ module Restic
247
256
  @auto_update_restic_service = do_update
248
257
  elsif update_target == 'restic'
249
258
  @auto_update_restic = do_update
259
+ elsif update_target == 'rclone'
260
+ @auto_update_rclone = do_update
250
261
  end
251
262
  end
252
263
 
@@ -268,12 +279,10 @@ module Restic
268
279
  if tool_path.relative?
269
280
  tool_path = find_in_path(tool_path)
270
281
  end
271
- if tool_path && tool_path.file?
272
- @tools[tool_name] = tool_path
273
- else
274
- STDERR.puts "cannot find path to #{tool_name}"
275
- @tools.delete(tool_name)
276
- end
282
+
283
+ exists = tool_path.file?
284
+ STDERR.puts "#{tool_path} does not exist" unless exists
285
+ @tools[tool_name] = [tool_path, exists]
277
286
  end
278
287
  end
279
288
  end
@@ -18,6 +18,7 @@ module Restic
18
18
  super
19
19
  @rclone_path = conf.tool_path('rclone')
20
20
  @src = yaml['src']
21
+ @filter = yaml['filter'] || []
21
22
  @conf_path = conf.conf_path
22
23
  end
23
24
 
@@ -39,6 +40,8 @@ EOCONF
39
40
  system(@rclone_path.to_path,
40
41
  '--transfers', '16',
41
42
  '--config', io.path,
43
+ '--delete-during',
44
+ *@filter.flat_map { |p| ['--filter', p] },
42
45
  *extra_args,
43
46
  'sync', @src, "restic-service:#{@bucket}/#{@path}", in: :close)
44
47
  end
@@ -1,5 +1,5 @@
1
1
  module Restic
2
2
  module Service
3
- VERSION = "0.2.2"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restic-service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Joyeux
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-03-16 00:00:00.000000000 Z
11
+ date: 2018-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor