mirrorworks 0.1.1 → 0.2.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 +4 -4
- data/README.md +19 -4
- data/example.mirrorworksrc.json +10 -7
- data/lib/mirrorworks.rb +66 -41
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e04d639d5a4487b53abdb576a77d782bdc077059
|
4
|
+
data.tar.gz: 16824c75ca849cdeb376ac42819ef043de3ed366
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23472f26451960e8ed4d3c8321b3c0c88f4f7b876c4ac1f105eade0f4590f06a28e059a978bccafe4f0ef80dfd1d6c068ce7bcf4fb05c29fd40af7eda586ce91
|
7
|
+
data.tar.gz: 581e9b76bb927ab16e73de91601a3e485e9676727f1319f20cef29eab3fa22827ba662ef5ae81593f6a37d63caaf1da19ad87725ccf156e26d08b76cfaa7c5f3
|
data/README.md
CHANGED
@@ -4,11 +4,11 @@ Mirrorworks
|
|
4
4
|
A handy rsync wrapper cli tool.
|
5
5
|
|
6
6
|
This is a dead-simple script that lets you easily set up pairs of files or
|
7
|
-
directories
|
7
|
+
directories - called 'reflections' - and sync them locally or over the network
|
8
8
|
with commands like
|
9
|
-
`$ mirrorworks push`
|
9
|
+
`$ mirrorworks push [reflection...]`
|
10
10
|
and
|
11
|
-
`$ mirrorworks pull`
|
11
|
+
`$ mirrorworks pull [reflection...]`
|
12
12
|
|
13
13
|
Installation and Configuration
|
14
14
|
------------------------------
|
@@ -21,7 +21,7 @@ Install the gem with
|
|
21
21
|
|
22
22
|
Mirrorworks reads a configuration file at ~/.mirrorworksrc.json.
|
23
23
|
To create an example config file run:
|
24
|
-
`$ mirrorworks
|
24
|
+
`$ mirrorworks setup`
|
25
25
|
|
26
26
|
This file contains some underlying rsync runtime options as well as a set of
|
27
27
|
'reflections'. Reflections are pairs files or directories that you want to have
|
@@ -38,6 +38,21 @@ Using Mirrorworks
|
|
38
38
|
The script is very straightforward. For usage, run
|
39
39
|
`$ mirrorworks --help`
|
40
40
|
|
41
|
+
Pushmodes/Pullmodes
|
42
|
+
-------------------
|
43
|
+
Since version 0.2.0, each reflection can optionally have a `pushmode` and a
|
44
|
+
`pullmode`. The value of each mode can be `soft`, `hard`, or `ignore`.
|
45
|
+
|
46
|
+
If a mode isn't included in the reflection, it will default to `soft`, which
|
47
|
+
does not delete any extra files when transferring (unless overridden with `-x`).
|
48
|
+
|
49
|
+
Using `hard` is the equivalent of supplying `-x` when running the command;
|
50
|
+
extra files on the destination that are not on the source will be deleted.
|
51
|
+
|
52
|
+
Providing `ignore` for a mode disables transfer for that mode. For example,
|
53
|
+
`"pushmode": "ignore"` would cause mirrorworks to always skip pushing that
|
54
|
+
reflection.
|
55
|
+
|
41
56
|
Development
|
42
57
|
-----------
|
43
58
|
For bug reports and feature requests, feel free to open an issue or make a
|
data/example.mirrorworksrc.json
CHANGED
@@ -1,22 +1,25 @@
|
|
1
1
|
{
|
2
2
|
"rsync_opts": [
|
3
3
|
"-rtupEl",
|
4
|
-
"--exclude=.git/*",
|
5
4
|
"--backup",
|
5
|
+
"--exclude=.git/*",
|
6
6
|
"--backup-dir=$HOME/.backup",
|
7
7
|
"--suffix=.$(date +%Y-%m-%d-%H-%M)"
|
8
8
|
],
|
9
9
|
|
10
10
|
"reflections": [
|
11
11
|
{
|
12
|
-
"name":
|
13
|
-
"local":
|
14
|
-
"remote":
|
12
|
+
"name": "first_example",
|
13
|
+
"local": "/dirs/end/with/slash/",
|
14
|
+
"remote": "me@example.com:~/dest/",
|
15
|
+
"pullmode": "soft"
|
15
16
|
},
|
16
17
|
{
|
17
|
-
"name":
|
18
|
-
"local":
|
19
|
-
"remote":
|
18
|
+
"name": "second_example",
|
19
|
+
"local": "$HOME/.mirrorworksrc.json",
|
20
|
+
"remote": "/public/mirrorworksrc.json",
|
21
|
+
"pushmode": "hard",
|
22
|
+
"pullmode": "ignore"
|
20
23
|
}
|
21
24
|
]
|
22
25
|
}
|
data/lib/mirrorworks.rb
CHANGED
@@ -3,14 +3,12 @@ require 'fileutils'
|
|
3
3
|
require 'rsync'
|
4
4
|
require 'json'
|
5
5
|
|
6
|
-
VERSION = '0.
|
6
|
+
VERSION = '0.2.0'
|
7
7
|
CONF_AT = File.join(Dir.home, '.mirrorworksrc.json')
|
8
8
|
|
9
9
|
class Mirrorworks
|
10
10
|
|
11
11
|
def initialize
|
12
|
-
@help_msg = ''
|
13
|
-
@options = {}
|
14
12
|
@conf = {}
|
15
13
|
end
|
16
14
|
|
@@ -18,10 +16,9 @@ class Mirrorworks
|
|
18
16
|
|
19
17
|
def parse_config
|
20
18
|
unless File.readable? CONF_AT
|
21
|
-
raise "Can't read #{CONF_AT}. Use '
|
19
|
+
raise "Can't read #{CONF_AT}. Use 'setup' command to make example conf."
|
22
20
|
end
|
23
21
|
File.open(CONF_AT, 'r') {|f| @conf = JSON.parse(f.read)}
|
24
|
-
@conf['rsync_opts'] << '--delete' if @options[:x]
|
25
22
|
end
|
26
23
|
|
27
24
|
def each_reflection(args)
|
@@ -46,17 +43,21 @@ class Mirrorworks
|
|
46
43
|
end
|
47
44
|
end
|
48
45
|
|
49
|
-
def
|
46
|
+
def setup
|
50
47
|
src = File.join(File.dirname(__FILE__), '..', 'example.mirrorworksrc.json')
|
51
48
|
raise "#{CONF_AT} already exists. Nothing to do." if File.exists? CONF_AT
|
52
49
|
FileUtils.cp(src, CONF_AT)
|
53
50
|
puts "Created example config at #{CONF_AT}"
|
54
51
|
end
|
55
52
|
|
56
|
-
def transfer(src, dest)
|
57
|
-
src.gsub
|
58
|
-
dest.gsub
|
59
|
-
|
53
|
+
def transfer(src, dest, runtime_vars)
|
54
|
+
src = src.gsub(' ', '\ ').gsub('(', '\(').gsub(')', '\)')
|
55
|
+
dest = dest.gsub(' ', '\ ').gsub('(', '\(').gsub(')', '\)')
|
56
|
+
opts = @conf['rsync_opts']
|
57
|
+
opts << '--delete' if runtime_vars[:hard]
|
58
|
+
opts << '--dry-run' if runtime_vars[:dry]
|
59
|
+
puts "rsync #{opts.join(' ')} #{src} #{dest}" if runtime_vars[:verbose]
|
60
|
+
result = Rsync.run(src, dest, opts)
|
60
61
|
raise result.error unless result.success?
|
61
62
|
result.changes.each do |c|
|
62
63
|
unless c.update_type == :no_update
|
@@ -64,40 +65,58 @@ class Mirrorworks
|
|
64
65
|
puts summary << "\t" << c.filename
|
65
66
|
end
|
66
67
|
end
|
67
|
-
puts
|
68
68
|
end
|
69
69
|
|
70
|
-
def push(args)
|
70
|
+
def push(args, runtime_vars)
|
71
71
|
each_reflection(args) do |ref|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
mode = ref['pushmode'].nil? ? 'soft' : ref['pushmode'].downcase
|
73
|
+
if mode == 'ignore'
|
74
|
+
puts "---- Ignoring push for #{ref['name']} ----"
|
75
|
+
else
|
76
|
+
runtime_vars[:hard] = true if mode == 'hard'
|
77
|
+
puts ">>>> Pushing #{ref['name']} >>>>"
|
78
|
+
src = ref['local']
|
79
|
+
dest = ref['remote']
|
80
|
+
transfer(src, dest, runtime_vars)
|
81
|
+
end
|
82
|
+
puts
|
76
83
|
end
|
77
84
|
end
|
78
85
|
|
79
|
-
def pull(args)
|
86
|
+
def pull(args, runtime_vars)
|
80
87
|
each_reflection(args) do |ref|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
88
|
+
mode = ref['pullmode'].nil? ? 'soft' : ref['pullmode'].downcase
|
89
|
+
if mode == 'ignore'
|
90
|
+
puts "---- Ignoring pull for #{ref['name']} ----"
|
91
|
+
else
|
92
|
+
runtime_vars[:hard] = true if mode == 'hard'
|
93
|
+
puts "<<<< Pulling #{ref['name']} <<<<"
|
94
|
+
src = ref['remote']
|
95
|
+
dest = ref['local']
|
96
|
+
transfer(src, dest, runtime_vars)
|
97
|
+
end
|
98
|
+
puts
|
85
99
|
end
|
86
100
|
end
|
87
101
|
|
88
|
-
def status(args)
|
102
|
+
def status(args, runtime_vars)
|
89
103
|
puts 'Starting dry run. No changes will be made.'
|
90
|
-
|
91
|
-
|
92
|
-
|
104
|
+
puts
|
105
|
+
runtime_vars[:dry] = true
|
106
|
+
push(args, runtime_vars)
|
107
|
+
pull(args, runtime_vars)
|
93
108
|
puts 'End of dry run.'
|
94
109
|
end
|
95
110
|
|
96
111
|
def list(args)
|
97
112
|
each_reflection(args) do |ref|
|
98
113
|
puts "Name: #{ref['name']}",
|
99
|
-
" Local:
|
100
|
-
" Remote:
|
114
|
+
" Local: #{ref['local']}",
|
115
|
+
" Remote: #{ref['remote']}",
|
116
|
+
" Pushmode: #{ref['pushmode'].nil? ?
|
117
|
+
'soft' : ref['pushmode'].downcase}",
|
118
|
+
" Pullmode: #{ref['pullmode'].nil? ?
|
119
|
+
'soft' : ref['pullmode'].downcase}",
|
101
120
|
''
|
102
121
|
end
|
103
122
|
end
|
@@ -107,11 +126,11 @@ class Mirrorworks
|
|
107
126
|
exit
|
108
127
|
end
|
109
128
|
|
110
|
-
def help
|
111
|
-
puts
|
129
|
+
def help(opts_msg)
|
130
|
+
puts opts_msg
|
112
131
|
puts '',
|
113
132
|
' Commands:',
|
114
|
-
'
|
133
|
+
' setup create example conf in home directory',
|
115
134
|
' push push from local to remote',
|
116
135
|
' pull pull from remote to local',
|
117
136
|
' status get status of reflections',
|
@@ -127,31 +146,37 @@ class Mirrorworks
|
|
127
146
|
|
128
147
|
def run(args)
|
129
148
|
begin
|
149
|
+
runtime_vars = {}
|
150
|
+
opts_msg = ''
|
130
151
|
OptionParser.new do |opts|
|
131
|
-
opts.banner =
|
152
|
+
opts.banner = "Usage: mirrorworks [options] <command> [reflections]\n"
|
153
|
+
opts.banner += ' Options:'
|
132
154
|
opts.on('-V', '--version', 'print version and exit') {version}
|
133
|
-
opts.on('-h', '--help', 'print help and exit') {help}
|
155
|
+
opts.on('-h', '--help', 'print help and exit') {help(opts_msg)}
|
156
|
+
opts.on('-v', '--verbose', 'show rsync command when executing') do |v|
|
157
|
+
runtime_vars[:verbose] = v
|
158
|
+
end
|
134
159
|
opts.on('-x', '--hard', 'delete extra files on transfer') do |x|
|
135
|
-
|
160
|
+
runtime_vars[:hard] = x
|
136
161
|
end
|
137
|
-
|
162
|
+
opts_msg = opts.to_s
|
138
163
|
end.parse! args
|
139
164
|
|
140
|
-
help if args.empty?
|
165
|
+
help(opts_msg) if args.empty?
|
141
166
|
|
142
167
|
command = args.shift
|
143
|
-
parse_config unless command == '
|
168
|
+
parse_config unless command == 'setup'
|
144
169
|
case command
|
145
170
|
when 'push'
|
146
|
-
push args
|
171
|
+
push args, runtime_vars
|
147
172
|
when 'pull'
|
148
|
-
pull args
|
173
|
+
pull args, runtime_vars
|
149
174
|
when 'status'
|
150
|
-
status args
|
175
|
+
status args, runtime_vars
|
151
176
|
when 'list'
|
152
177
|
list args
|
153
|
-
when '
|
154
|
-
|
178
|
+
when 'setup'
|
179
|
+
setup
|
155
180
|
else
|
156
181
|
raise "No command '#{command}'"
|
157
182
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mirrorworks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tyler Brazier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rsync
|