snapsync 0.3.0 → 0.3.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.
- checksums.yaml +4 -4
- data/Rakefile +2 -1
- data/install.sh +2 -2
- data/lib/snapsync/cli.rb +91 -20
- data/lib/snapsync/exceptions.rb +2 -0
- data/lib/snapsync/local_target.rb +38 -10
- data/lib/snapsync/test.rb +1 -1
- data/lib/snapsync/timeline_sync_policy.rb +4 -1
- data/lib/snapsync/version.rb +1 -1
- data/snapsync.gemspec +2 -1
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6537d4331f2602702b307130fda024bdab894efa
|
4
|
+
data.tar.gz: ee06446c1c840e41217616528ec5ac10e29db0cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a128cafd4224ebac10c98d333e90c3fee57812d19e9c57f5460b626d7008c302e28f7b3730d1b0535ae3f8230d80578f1020a0d0f926071ddd5de2d861526c63
|
7
|
+
data.tar.gz: 32cb9bb06f3340f10f7b2087ee4eb63a8f4411f7c421155420c7b1b264b03f6118e25fb93c05d95d7b2cd1e7bc307fa36b03b6801347ba0b5536e8effb241f47
|
data/Rakefile
CHANGED
data/install.sh
CHANGED
@@ -10,8 +10,9 @@ GEMFILE
|
|
10
10
|
bundler install --standalone --binstubs
|
11
11
|
if test -d /opt/snapsync; then
|
12
12
|
sudo rm -rf /opt/snapsync
|
13
|
-
sudo cp -r . /opt/snapsync
|
14
13
|
fi
|
14
|
+
sudo cp -r . /opt/snapsync
|
15
|
+
sudo chmod go+rX /opt/snapsync
|
15
16
|
|
16
17
|
if test -d /lib/systemd/system; then
|
17
18
|
snapsync_gem=`bundler show snapsync`
|
@@ -22,4 +23,3 @@ if test -d /lib/systemd/system; then
|
|
22
23
|
fi
|
23
24
|
|
24
25
|
rm -rf $target
|
25
|
-
|
data/lib/snapsync/cli.rb
CHANGED
@@ -52,6 +52,11 @@ module Snapsync
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
55
|
+
|
56
|
+
def partition_of(dir)
|
57
|
+
partitions = PartitionsMonitor.new
|
58
|
+
PartitionsMonitor.new.partition_of(dir)
|
59
|
+
end
|
55
60
|
end
|
56
61
|
|
57
62
|
desc 'sync CONFIG DIR', 'synchronizes the snapper configuration CONFIG with the snapsync target DIR'
|
@@ -91,8 +96,27 @@ module Snapsync
|
|
91
96
|
end
|
92
97
|
end
|
93
98
|
|
94
|
-
|
99
|
+
no_commands do
|
100
|
+
def normalize_policy(args)
|
101
|
+
policy =
|
102
|
+
if args.empty?
|
103
|
+
['default', Array.new]
|
104
|
+
elsif args.size == 1
|
105
|
+
args + [Array.new]
|
106
|
+
else
|
107
|
+
[args.shift, args]
|
108
|
+
end
|
109
|
+
|
110
|
+
LocalTarget.parse_policy(*policy)
|
111
|
+
return *policy
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
desc 'init [NAME] DIR [POLICY]', 'creates a synchronization target, optionally adding it to the auto-sync targets and specifying the synchronization and cleanup policies'
|
95
116
|
long_desc <<-EOD
|
117
|
+
NAME must be provided if DIR is to be added to the auto-sync targets (which
|
118
|
+
is the default).
|
119
|
+
|
96
120
|
By default, the default policy is used. To change this, provide additional
|
97
121
|
arguments as would be expected by the policy subcommand. Run snapsync help
|
98
122
|
policy for more information
|
@@ -103,13 +127,52 @@ policy for more information
|
|
103
127
|
desc: "if true (the default), add the newly created target to auto-sync"
|
104
128
|
option :automount, type: :boolean, default: true,
|
105
129
|
desc: 'whether the supporting partition should be auto-mounted by snapsync when needed or not (the default is yes). Only useful if --no-auto has not been provided on the command line.'
|
106
|
-
|
130
|
+
option :config_file, default: '/etc/snapsync.conf',
|
131
|
+
desc: 'the configuration file that should be updated'
|
132
|
+
def init(*args)
|
133
|
+
if options[:auto] && !options[:all]
|
134
|
+
raise ArgumentError, "cannot use --auto without --all"
|
135
|
+
end
|
136
|
+
|
137
|
+
if options[:auto]
|
138
|
+
if args.size < 2
|
139
|
+
self.class.handle_argument_error(self.class.all_commands['init'], nil, args, 2)
|
140
|
+
end
|
141
|
+
name, dir, *policy = *args
|
142
|
+
else
|
143
|
+
if args.size < 1
|
144
|
+
self.class.handle_argument_error(self.class.all_commands['init'], nil, args, 1)
|
145
|
+
end
|
146
|
+
dir, *policy = *args
|
147
|
+
end
|
107
148
|
dir = Pathname.new(dir)
|
108
149
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
150
|
+
# Parse the policy option early to avoid breaking later
|
151
|
+
begin
|
152
|
+
policy = normalize_policy(policy)
|
153
|
+
rescue Exception
|
154
|
+
# Try to see if the user forgot to add the NAME option or added
|
155
|
+
# the name option but should not have
|
156
|
+
if options[:auto]
|
157
|
+
valid_policy = begin normalize_policy(args[1..-1])
|
158
|
+
true
|
159
|
+
rescue InvalidConfiguration
|
160
|
+
false
|
161
|
+
end
|
162
|
+
if valid_policy
|
163
|
+
raise ArgumentError, "--auto is set but it seems that you did not provide a name"
|
164
|
+
end
|
165
|
+
else
|
166
|
+
valid_policy = begin normalize_policy(args[2..-1])
|
167
|
+
true
|
168
|
+
rescue InvalidConfiguration
|
169
|
+
false
|
170
|
+
end
|
171
|
+
if valid_policy
|
172
|
+
raise ArgumentError, "--auto is not set but it seems that you provided a name"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
raise ArgumentError, "invalid policy #{policy}"
|
113
176
|
end
|
114
177
|
|
115
178
|
dirs = Array.new
|
@@ -134,31 +197,39 @@ policy for more information
|
|
134
197
|
end
|
135
198
|
end
|
136
199
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
auto_add(name, dir)
|
142
|
-
end
|
200
|
+
# We check that both options are set together for some added safety,
|
201
|
+
# but it's checked at the top of the method
|
202
|
+
if options[:auto] && options[:all]
|
203
|
+
auto_add(name, dir)
|
143
204
|
end
|
144
205
|
end
|
145
206
|
|
146
207
|
desc 'auto-add NAME DIR', "add DIR to the set of targets for auto-sync"
|
147
208
|
option :automount, type: :boolean, default: true,
|
148
209
|
desc: 'whether the supporting partition should be auto-mounted by snapsync when needed or not (the default is yes)'
|
210
|
+
option :config_file, default: '/etc/snapsync.conf',
|
211
|
+
desc: 'the configuration file that should be updated'
|
149
212
|
def auto_add(name, dir)
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
conf_path = Pathname.new('/etc/snapsync.conf')
|
213
|
+
uuid, relative = partition_of(Pathname.new(dir))
|
214
|
+
conf_path = Pathname.new(options[:config_file])
|
154
215
|
|
155
216
|
autosync = AutoSync.new
|
156
|
-
|
217
|
+
if conf_path.exist?
|
218
|
+
autosync.load_config(conf_path)
|
219
|
+
end
|
157
220
|
exists = autosync.each_autosync_target.find do |t|
|
158
221
|
t.partition_uuid == uuid && t.path.cleanpath == relative.cleanpath
|
159
222
|
end
|
160
223
|
if exists
|
161
|
-
if exists.
|
224
|
+
if !exists.name
|
225
|
+
if (exists.automount ^ options[:automount]) && name
|
226
|
+
Snapsync.info "already exists without a name, setting the name to #{name}"
|
227
|
+
elsif name
|
228
|
+
Snapsync.info "already exists without a name and a different automount flag, setting the name to #{name} and updating the automount flag"
|
229
|
+
else
|
230
|
+
Snapsync.info "already exists with different automount flag, updating"
|
231
|
+
end
|
232
|
+
elsif exists.automount == options[:automount]
|
162
233
|
Snapsync.info "already exists under the name #{exists.name}"
|
163
234
|
else
|
164
235
|
Snapsync.info "already exists under the name #{exists.name} but with a different automount flag, changing"
|
@@ -197,6 +268,8 @@ for 10 days). snapsync understands the following period names: year month day ho
|
|
197
268
|
EOD
|
198
269
|
def policy(dir, type, *options)
|
199
270
|
handle_class_options
|
271
|
+
# Parse the policy early to avoid breaking later
|
272
|
+
LocalTarget.parse_policy(*policy)
|
200
273
|
each_target(dir) do |_, target|
|
201
274
|
target.change_policy(type, options)
|
202
275
|
target.write_config
|
@@ -231,9 +304,7 @@ While it can easily be done manually, this command makes sure that the snapshots
|
|
231
304
|
desc 'list [DIR]', 'list the snapshots present on DIR. If DIR is omitted, tries to access all targets defined as auto-sync targets'
|
232
305
|
def list(dir = nil)
|
233
306
|
handle_class_options
|
234
|
-
matched_uuids = Set.new
|
235
307
|
each_target(dir) do |_, target|
|
236
|
-
matched_uuids << target.uuid
|
237
308
|
puts "== #{target.dir}"
|
238
309
|
puts "UUID: #{target.uuid}"
|
239
310
|
puts "Enabled: #{target.enabled?}"
|
data/lib/snapsync/exceptions.rb
CHANGED
@@ -5,4 +5,6 @@ module Snapsync
|
|
5
5
|
# Exception raised when a snapshot directory is given to {Snapshot} but
|
6
6
|
# snapshot_dir/info.xml does not look like a valid snapper info file.
|
7
7
|
class InvalidInfoFile < InvalidSnapshot; end
|
8
|
+
# Invalid configuration requested
|
9
|
+
class InvalidConfiguration < ArgumentError; end
|
8
10
|
end
|
@@ -75,14 +75,17 @@ module Snapsync
|
|
75
75
|
config['enabled'] = enabled?
|
76
76
|
config['autoclean'] = autoclean?
|
77
77
|
|
78
|
-
|
79
|
-
|
78
|
+
config_path.open('w') do |io|
|
79
|
+
YAML.dump(config, io)
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
83
|
def read_config
|
84
84
|
begin
|
85
|
-
raw_config = YAML.load(config_path.read)
|
85
|
+
if !(raw_config = YAML.load(config_path.read))
|
86
|
+
raise NoUUIDError, "empty configuration file found in #{config_path}"
|
87
|
+
end
|
88
|
+
|
86
89
|
rescue Errno::ENOENT => e
|
87
90
|
raise NoUUIDError, e.message, e.backtrace
|
88
91
|
end
|
@@ -113,26 +116,51 @@ module Snapsync
|
|
113
116
|
def config_path
|
114
117
|
dir + "snapsync.config"
|
115
118
|
end
|
116
|
-
|
117
|
-
|
119
|
+
|
120
|
+
# Parse a policy specification as provided on the command line or saved
|
121
|
+
# in the config file into sync and cleanup policy objects
|
122
|
+
#
|
123
|
+
# @param [String] type the policy type, either default, timeline or last
|
124
|
+
# @param [Array<String>] options to be passed to the #from_config method
|
125
|
+
# on the underlying policy classes
|
126
|
+
#
|
127
|
+
# @return [(#filter_snapshots,#filter_snapshots)] the sync policy
|
128
|
+
# and the cleanup policy. The cleanup policy might be nil
|
129
|
+
# @raise [InvalidConfiguration] if the policy type is unknown
|
130
|
+
# @see DefaultSyncPolicy TimelineSyncPolicy SyncLastPolicy
|
131
|
+
def self.parse_policy(type, options)
|
118
132
|
case type
|
119
133
|
when 'default'
|
120
134
|
sync_policy = DefaultSyncPolicy
|
121
|
-
cleanup
|
135
|
+
cleanup = nil
|
122
136
|
when 'timeline'
|
123
137
|
sync_policy = TimelineSyncPolicy
|
124
|
-
cleanup
|
138
|
+
cleanup = TimelineSyncPolicy
|
125
139
|
when 'last'
|
126
140
|
sync_policy = SyncLastPolicy
|
127
|
-
cleanup
|
141
|
+
cleanup = SyncLastPolicy
|
128
142
|
else
|
129
143
|
raise InvalidConfiguration, "synchronization policy #{type} does not exist"
|
130
144
|
end
|
131
|
-
|
132
|
-
|
145
|
+
sync_policy = sync_policy.from_config(options)
|
146
|
+
cleanup =
|
133
147
|
if cleanup
|
134
148
|
Cleanup.new(cleanup.from_config(options))
|
135
149
|
end
|
150
|
+
return sync_policy, cleanup
|
151
|
+
end
|
152
|
+
|
153
|
+
# Verifies that the given policy type and options are valid
|
154
|
+
def self.valid_policy?(type, options)
|
155
|
+
parse_policy(type, options)
|
156
|
+
true
|
157
|
+
rescue InvalidConfiguration
|
158
|
+
false
|
159
|
+
end
|
160
|
+
|
161
|
+
def change_policy(type, options)
|
162
|
+
@sync_policy, @cleanup =
|
163
|
+
self.class.parse_policy(type, options)
|
136
164
|
end
|
137
165
|
|
138
166
|
def delete(s, dry_run: false)
|
data/lib/snapsync/test.rb
CHANGED
@@ -19,7 +19,10 @@ module Snapsync
|
|
19
19
|
|
20
20
|
def parse_config(config)
|
21
21
|
config.each_slice(2) do |period, count|
|
22
|
-
add(period.to_sym, Integer(count))
|
22
|
+
begin add(period.to_sym, Integer(count))
|
23
|
+
rescue ArgumentError
|
24
|
+
raise InvalidConfiguration, "invalid timeline period or count #{period} #{count}"
|
25
|
+
end
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
data/lib/snapsync/version.rb
CHANGED
data/snapsync.gemspec
CHANGED
@@ -31,5 +31,6 @@ EOD
|
|
31
31
|
spec.add_development_dependency "bundler", "~> 1.10"
|
32
32
|
spec.add_development_dependency "rake", "~> 10.0"
|
33
33
|
spec.add_development_dependency "minitest", "~> 5.0", ">= 5.7"
|
34
|
-
spec.add_development_dependency "flexmock", "~>
|
34
|
+
spec.add_development_dependency "flexmock", "~> 2.0", ">= 2.0"
|
35
|
+
spec.add_development_dependency "fakefs"
|
35
36
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snapsync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Joyeux
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logging
|
@@ -144,20 +144,34 @@ dependencies:
|
|
144
144
|
requirements:
|
145
145
|
- - "~>"
|
146
146
|
- !ruby/object:Gem::Version
|
147
|
-
version: '
|
147
|
+
version: '2.0'
|
148
148
|
- - ">="
|
149
149
|
- !ruby/object:Gem::Version
|
150
|
-
version:
|
150
|
+
version: '2.0'
|
151
151
|
type: :development
|
152
152
|
prerelease: false
|
153
153
|
version_requirements: !ruby/object:Gem::Requirement
|
154
154
|
requirements:
|
155
155
|
- - "~>"
|
156
156
|
- !ruby/object:Gem::Version
|
157
|
-
version: '
|
157
|
+
version: '2.0'
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '2.0'
|
161
|
+
- !ruby/object:Gem::Dependency
|
162
|
+
name: fakefs
|
163
|
+
requirement: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
type: :development
|
169
|
+
prerelease: false
|
170
|
+
version_requirements: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
158
172
|
- - ">="
|
159
173
|
- !ruby/object:Gem::Version
|
160
|
-
version:
|
174
|
+
version: '0'
|
161
175
|
description: |
|
162
176
|
Snapsync is a tool that automates transferring snapper snapshots to
|
163
177
|
external media (USB drives ...) and managing these snapshots (e.g.
|