remotesync 1.0.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 +7 -0
- data/bin/rrinit +184 -0
- data/bin/rrpull +75 -0
- data/bin/rrpush +35 -0
- data/lib/commons.rb +284 -0
- metadata +70 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 13cc5deafe2ae0fa3348ac64b6212feef2b8df773b4005a49d134652e86a99d4
|
4
|
+
data.tar.gz: 9cb6df03332a34df4320776273ec54b4327b1f49cae294e599ef9decc24063a3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 892ac784c4fd58041b470056d862d1b0c8e57a31f889d4857cbedd27ad2af05b766dc9d3ab39b0de6798a174f23d683f7a90ec05c9271edc86ffc4ce0047c3d7
|
7
|
+
data.tar.gz: f65bf5a6b664b96078fda80e56b0cab90f9f61acc28331a1c235e015e62f66d7984de0716df9a1f551e36fc92d1e59202f33315226baafb9e699a89b562132d6
|
data/bin/rrinit
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require_relative "../lib/commons"
|
4
|
+
|
5
|
+
args = CmdParser.setup(INIT_COMMAND, :hostname, :path) do |opts|
|
6
|
+
CmdParser.autoset_param "-pPORT", "--port=PORT", "Port of the remote host", :port, [:propagate, :delete, :unlock, :status]
|
7
|
+
CmdParser.autoset_param "-uUSER", "--user=USER", "User of the remote host", :user, [:propagate, :delete, :unlock, :status]
|
8
|
+
CmdParser.autoset_param "-nNETNS", "--netns=NETNS", "Network namespace", :netns, [:propagate, :delete, :unlock, :status]
|
9
|
+
CmdParser.autoset_param "-oOWNER", "--owner=OWNER", "Ownership of the files (defaults to the current user)", :owner, [:propagate, :delete, :unlock, :status]
|
10
|
+
|
11
|
+
CmdParser.autoset_flag "-r", "--recursive", "Ownership of the files (defaults to the current user)", :recursive, [:propagate]
|
12
|
+
CmdParser.autoset_flag "-f", "--force", "Force the overwrite of existing data", :force
|
13
|
+
CmdParser.autoset_flag "-R", "--pull-only", "Allows only the pull from the remote", :pullonly, [:pushonly]
|
14
|
+
CmdParser.autoset_flag "-W", "--push-only", "Allows only the push to the remote", :pushonly, [:pullonly]
|
15
|
+
|
16
|
+
CmdParser.autoset_flag "-D", "--delete", "Delete all the sync files (asks for confirmation)", :delete, [:propagate, :unlock, :status]
|
17
|
+
CmdParser.autoset_flag "-p", "--propagate", "Propagate the root file to all the sub-directories", :propagate, [:delete, :unlock, :status]
|
18
|
+
CmdParser.autoset_flag "-u", "--unlock", "Unlock all the remote information files", :unlock, [:delete, :propagate, :status]
|
19
|
+
CmdParser.autoset_flag "-s", "--status", "Prints the status of the folder", :status, [:delete, :propagate, :unlock]
|
20
|
+
end
|
21
|
+
|
22
|
+
if CmdParser.opt :delete
|
23
|
+
unless FileTest.exists? RemoteInfo.filename(".")
|
24
|
+
puts "This folder is not initialized yet. " + "Deletion aborted.".red
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
|
28
|
+
sub = CmdParser.opt(:recursive) ? " and its subdirectories" : ""
|
29
|
+
print "Are you sure you want to delete all the sync information in this directory#{sub}? [y/N] "
|
30
|
+
confirm = gets.chomp.downcase
|
31
|
+
if confirm != "y"
|
32
|
+
puts "Aborted.".red
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
|
36
|
+
print "Deleting all the remote files... "
|
37
|
+
puts "" if CmdParser.opt :verbose
|
38
|
+
FS.each_folder(".", CmdParser.opt(:recursive)) do |current|
|
39
|
+
vputs "Deleting remote information file for #{current}"
|
40
|
+
OS.remove_file RemoteInfo.filename(current)
|
41
|
+
end
|
42
|
+
|
43
|
+
puts "Done!".green
|
44
|
+
exit
|
45
|
+
|
46
|
+
elsif CmdParser.opt :propagate
|
47
|
+
print "Propagating the remote information to all the subfolders... "
|
48
|
+
unless FileTest.exists? RemoteInfo.filename(".")
|
49
|
+
puts "\n" + "Error".red + ": Initialize this directory first. Aborting propagation."
|
50
|
+
exit
|
51
|
+
end
|
52
|
+
|
53
|
+
rfile = RemoteInfo.load
|
54
|
+
|
55
|
+
CmdParser.set :port, rfile.port
|
56
|
+
CmdParser.set :user, rfile.user
|
57
|
+
CmdParser.set :netns, rfile.netns
|
58
|
+
CmdParser.set :owner, rfile.owner
|
59
|
+
CmdParser.set :recursive, true
|
60
|
+
args[:hostname] = rfile.host
|
61
|
+
args[:path] = rfile.path
|
62
|
+
|
63
|
+
vputs "\nPropagation information:"
|
64
|
+
vputs "\tHost: #{rfile.host}"
|
65
|
+
vputs "\tPath: #{rfile.path}"
|
66
|
+
vputs "\tPort: #{rfile.port}" if rfile.port
|
67
|
+
vputs "\tUser: #{rfile.user}" if rfile.user
|
68
|
+
vputs "\tNetwork namespace: #{rfile.netns}" if rfile.netns
|
69
|
+
vputs "\tOwner: #{rfile.owner}" if rfile.owner
|
70
|
+
#Does propagation through the normal procedure
|
71
|
+
|
72
|
+
elsif CmdParser.opt :unlock
|
73
|
+
print "Unlocking all the remote files... "
|
74
|
+
RemoteInfo.unlock_all current
|
75
|
+
puts "Done!".green
|
76
|
+
exit
|
77
|
+
|
78
|
+
elsif CmdParser.opt :status
|
79
|
+
unless FileTest.exists? RemoteInfo.filename(".")
|
80
|
+
puts "This folder is not initialized yet."
|
81
|
+
exit
|
82
|
+
end
|
83
|
+
|
84
|
+
rinfo = RemoteInfo.load "."
|
85
|
+
userstring = rinfo.user ? rinfo.user.to_s + "@" : ""
|
86
|
+
portstring = rinfo.port ? ":"+rinfo.port.to_s : ""
|
87
|
+
|
88
|
+
mode = []
|
89
|
+
if rinfo.can_push?
|
90
|
+
mode.push "Push".green
|
91
|
+
else
|
92
|
+
mode.push "Push".red
|
93
|
+
end
|
94
|
+
|
95
|
+
if rinfo.can_pull?
|
96
|
+
mode.push "Pull".green
|
97
|
+
else
|
98
|
+
mode.push "Pull".red
|
99
|
+
end
|
100
|
+
modestring = mode.join("|")
|
101
|
+
|
102
|
+
puts "Root remote information:"
|
103
|
+
puts "\tHost: #{userstring}#{rinfo.host}#{portstring}"
|
104
|
+
puts "\tPath: #{rinfo.path}"
|
105
|
+
puts "\tNetwork namespace: #{rinfo.netns}" if rinfo.netns
|
106
|
+
puts "\tOwner: #{rinfo.owner}" if rinfo.owner
|
107
|
+
puts "\tMode: #{modestring}"
|
108
|
+
|
109
|
+
puts "Local folders:"
|
110
|
+
ignore = []
|
111
|
+
FS.each_folder(".", true) do |current|
|
112
|
+
next if current == "."
|
113
|
+
|
114
|
+
skip = false
|
115
|
+
ignore.each do |ig|
|
116
|
+
skip = true if current.start_with? ig
|
117
|
+
end
|
118
|
+
next if skip
|
119
|
+
|
120
|
+
valid = File.join(rinfo.path, current)
|
121
|
+
|
122
|
+
status = ""
|
123
|
+
if FileTest.exists? RemoteInfo.filename(current)
|
124
|
+
cinfo = RemoteInfo.load current
|
125
|
+
|
126
|
+
if cinfo.path != valid || cinfo.host != rinfo.host
|
127
|
+
status = "DIFFERENT REMOTE".yellow + "(" + ScpUtils.remote(nil, cinfo) + ")"
|
128
|
+
ignore.push current
|
129
|
+
else
|
130
|
+
status = "OK".green
|
131
|
+
end
|
132
|
+
else
|
133
|
+
status = "LOCAL ONLY".red
|
134
|
+
ignore.push current
|
135
|
+
end
|
136
|
+
puts "\t- #{current}: #{status}"
|
137
|
+
end
|
138
|
+
exit
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
err = false
|
144
|
+
unless args[:hostname]
|
145
|
+
puts "Error".red + ": You have to specify the remote hostname."
|
146
|
+
err = true
|
147
|
+
end
|
148
|
+
|
149
|
+
unless args[:path]
|
150
|
+
puts "Error".red + ": You have to specify the remote path."
|
151
|
+
err = true
|
152
|
+
end
|
153
|
+
|
154
|
+
if err
|
155
|
+
puts "Try #{INIT_COMMAND} -h to check how to use this command"
|
156
|
+
exit
|
157
|
+
end
|
158
|
+
|
159
|
+
unless CmdParser.opt :propagate
|
160
|
+
sub = CmdParser.opt(:recursive) ? " and its subdirectories" : ""
|
161
|
+
print "Initializing the directory#{sub}... "
|
162
|
+
end
|
163
|
+
|
164
|
+
FS.each_folder(".", CmdParser.opt(:recursive)) do |current|
|
165
|
+
if CmdParser.opt(:force) || !FileTest.exists?(RemoteInfo.filename(current))
|
166
|
+
rfile = RemoteInfo.new
|
167
|
+
rfile.port = CmdParser.opt :port
|
168
|
+
rfile.user = CmdParser.opt :user
|
169
|
+
rfile.netns = CmdParser.opt :netns
|
170
|
+
rfile.owner = CmdParser.opt :owner
|
171
|
+
rfile.operations = "w" if CmdParser.opt :pushonly
|
172
|
+
rfile.operations = "r" if CmdParser.opt :pullonly
|
173
|
+
|
174
|
+
rfile.host = args[:hostname]
|
175
|
+
rfile.path = (current != "." ? File.join(args[:path], current) : args[:path])
|
176
|
+
|
177
|
+
vputs "Writing remote information for #{current}..."
|
178
|
+
rfile.save_info current
|
179
|
+
else
|
180
|
+
vputs "Skipping #{current} (already exists)..."
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
puts "Done!".green
|
data/bin/rrpull
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require_relative "../lib/commons"
|
4
|
+
|
5
|
+
args = CmdParser.setup(PULL_COMMAND) do |opts|
|
6
|
+
CmdParser.autoset_param "-fFILE", "--file=FILE", "File to push", :file, [:directory]
|
7
|
+
CmdParser.autoset_param "-dDIR", "--directory=DIR", "Directory to push", :directory, [:file]
|
8
|
+
|
9
|
+
CmdParser.autoset_param "-oOWNER", "--owner=OWNER", "Ownership of the files (defaults to the current user)", :owner
|
10
|
+
end
|
11
|
+
|
12
|
+
unless FileTest.exists? RemoteInfo.filename(".")
|
13
|
+
puts "Error".red + ": please, use #{INIT_COMMAND} before #{PULL_COMMAND}"
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
|
17
|
+
remote_info = RemoteInfo.load
|
18
|
+
|
19
|
+
unless remote_info.can_pull?
|
20
|
+
puts "Error".red + ": pull forbidden (push-only directory). Aborted."
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
|
24
|
+
isdir = !CmdParser.opt(:file)
|
25
|
+
|
26
|
+
OS.run "mkdir -p \"#{CmdParser.opt(:directory)}\"" if CmdParser.opt(:directory)
|
27
|
+
|
28
|
+
#Lock all the remote information files
|
29
|
+
RemoteInfo.lock_all(CmdParser.opt(:directory) || ".", isdir) do
|
30
|
+
vputs "Locked all the remote information files in the path"
|
31
|
+
local = ScpUtils.local CmdParser.opt(:file), CmdParser.opt(:directory)
|
32
|
+
remote = ScpUtils.remote local, remote_info
|
33
|
+
remote = File.join(remote, ".")
|
34
|
+
|
35
|
+
command = ScpUtils.scp remote, local, isdir, remote_info.port
|
36
|
+
|
37
|
+
new_owner = CmdParser.opt(:owner) || remote_info.owner || OS.username
|
38
|
+
result = nil
|
39
|
+
if remote_info.netns
|
40
|
+
puts "Requiring root privileges to run in network namespace..."
|
41
|
+
result = OS.run "sudo ip netns exec #{remote_info.netns} #{command}"
|
42
|
+
new_owner = OS.username unless new_owner
|
43
|
+
else
|
44
|
+
result = OS.run command
|
45
|
+
end
|
46
|
+
|
47
|
+
unless result
|
48
|
+
puts "An error occurred while executing the copy command. Exiting"
|
49
|
+
RemoteInfo.unlock_all
|
50
|
+
exit
|
51
|
+
end
|
52
|
+
|
53
|
+
result[1].split("\n").each do |errline|
|
54
|
+
if errline.downcase.include?("permission denied") && !errline.downcase.include?(RemoteInfo::FILENAME)
|
55
|
+
puts "Error:" + errline
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if new_owner
|
60
|
+
puts "Requiring root privileges to change ownership..."
|
61
|
+
OS.run "sudo chown #{new_owner} \"#{local}\" #{isdir ? "-R" : ""}"
|
62
|
+
end
|
63
|
+
vputs "Unlocked all the remote information files in the path"
|
64
|
+
end
|
65
|
+
|
66
|
+
rinit_script = File.join File.expand_path(File.dirname(__FILE__)), INIT_COMMAND
|
67
|
+
#Propagates the creation of remote file to all the new subfolders
|
68
|
+
vputs "Calling #{INIT_COMMAND} to propagate the information..."
|
69
|
+
result = OS.run "ruby \"#{rinit_script}\" -p"
|
70
|
+
puts result[0]
|
71
|
+
if result[1] != ""
|
72
|
+
puts "Error".red + ":" + result[1]
|
73
|
+
end
|
74
|
+
|
75
|
+
puts "The local version is up to date.".green
|
data/bin/rrpush
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require_relative "../lib/commons"
|
4
|
+
|
5
|
+
args = CmdParser.setup(PUSH_COMMAND) do |opts|
|
6
|
+
CmdParser.autoset_param "-fFILE", "--file=FILE", "File to push", :file, [:directory]
|
7
|
+
CmdParser.autoset_param "-dDIR", "--directory=DIR", "Directory to push", :directory, [:file]
|
8
|
+
end
|
9
|
+
|
10
|
+
unless FileTest.exists? RemoteInfo.filename(".")
|
11
|
+
puts "Error".red + ": please, use #{INIT_COMMAND} before #{PUSH_COMMAND}"
|
12
|
+
exit
|
13
|
+
end
|
14
|
+
|
15
|
+
remote_info = RemoteInfo.load
|
16
|
+
|
17
|
+
unless remote_info.can_push?
|
18
|
+
puts "Error".red + ": push forbidden (pull-only directory). Aborted."
|
19
|
+
exit
|
20
|
+
end
|
21
|
+
|
22
|
+
isdir = !CmdParser.opt(:file)
|
23
|
+
|
24
|
+
local = ScpUtils.local CmdParser.opt(:file), CmdParser.opt(:directory)
|
25
|
+
remote = ScpUtils.remote local, remote_info
|
26
|
+
|
27
|
+
command = ScpUtils.scp local, remote, isdir, remote_info.port
|
28
|
+
if remote_info.netns
|
29
|
+
puts "Requiring root privileges to run in network namespace..."
|
30
|
+
OS.run "sudo ip netns exec #{remote_info.netns} #{command}"
|
31
|
+
else
|
32
|
+
OS.run command
|
33
|
+
end
|
34
|
+
|
35
|
+
puts "The remote version is up to date.".green
|
data/lib/commons.rb
ADDED
@@ -0,0 +1,284 @@
|
|
1
|
+
require "optparse"
|
2
|
+
require "open3"
|
3
|
+
require "colorize"
|
4
|
+
|
5
|
+
INIT_COMMAND = "rrinit"
|
6
|
+
PUSH_COMMAND = "rrpush"
|
7
|
+
PULL_COMMAND = "rrpull"
|
8
|
+
|
9
|
+
class RemoteInfo
|
10
|
+
FILENAME = ".reminfo"
|
11
|
+
|
12
|
+
attr_accessor :host
|
13
|
+
attr_accessor :port
|
14
|
+
attr_accessor :user
|
15
|
+
attr_accessor :path
|
16
|
+
attr_accessor :netns
|
17
|
+
attr_accessor :owner
|
18
|
+
attr_accessor :operations
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@netns = nil
|
22
|
+
@owner = nil
|
23
|
+
|
24
|
+
@port = nil
|
25
|
+
@user = nil
|
26
|
+
|
27
|
+
@operations = "rw"
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.load(folder=".")
|
31
|
+
rinfo = RemoteInfo.new
|
32
|
+
rinfo.read_info(folder)
|
33
|
+
return rinfo
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.filename(folder)
|
37
|
+
return File.join(folder, FILENAME)
|
38
|
+
end
|
39
|
+
|
40
|
+
def can_pull?
|
41
|
+
return @operations.include? "r"
|
42
|
+
end
|
43
|
+
|
44
|
+
def can_push?
|
45
|
+
return @operations.include? "w"
|
46
|
+
end
|
47
|
+
|
48
|
+
def read_info(folder)
|
49
|
+
info = File.read(File.join(folder, FILENAME))
|
50
|
+
|
51
|
+
rows = info.split "\n"
|
52
|
+
rows.each do |r|
|
53
|
+
key, value = *r.split("\t")
|
54
|
+
|
55
|
+
key = key.strip
|
56
|
+
value = value.strip
|
57
|
+
|
58
|
+
case key
|
59
|
+
when "host"
|
60
|
+
@host = value
|
61
|
+
when "port"
|
62
|
+
@port = value
|
63
|
+
when "user"
|
64
|
+
@user = value
|
65
|
+
when "path"
|
66
|
+
@path = value
|
67
|
+
when "netns"
|
68
|
+
@netns = value
|
69
|
+
when "owner"
|
70
|
+
@owner = value
|
71
|
+
when "operations"
|
72
|
+
@operations = value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def save_info(to=".")
|
78
|
+
content = ""
|
79
|
+
content += "host\t#@host\n"
|
80
|
+
content += "port\t#@port\n" if @port
|
81
|
+
content += "user\t#@user\n" if @user
|
82
|
+
content += "path\t#@path\n"
|
83
|
+
content += "netns\t#@netns\n" if @netns
|
84
|
+
content += "owner\t#@owner\n" if @owner
|
85
|
+
content += "operations\t#@operations\n"
|
86
|
+
|
87
|
+
dest = to ? File.join(to, FILENAME) : FILENAME
|
88
|
+
|
89
|
+
File.write dest, content
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.unlock_all(local)
|
93
|
+
self.lock_all(local, true) {}
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.lock_all(local, prevent_write=true)
|
97
|
+
if (prevent_write)
|
98
|
+
FS.each_remote_info(local) do |rinfo|
|
99
|
+
OS.run "chmod -w \"#{rinfo}\""
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
yield
|
104
|
+
|
105
|
+
if (prevent_write)
|
106
|
+
FS.each_remote_info(local) do |rinfo|
|
107
|
+
OS.run "chmod +w \"#{rinfo}\""
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class FS
|
114
|
+
def self.each_folder(dir, recursive=true)
|
115
|
+
queue = ["."]
|
116
|
+
visited = []
|
117
|
+
while queue.size > 0
|
118
|
+
current = queue.shift
|
119
|
+
|
120
|
+
yield current
|
121
|
+
|
122
|
+
if recursive
|
123
|
+
Dir.entries(current).each do |entry|
|
124
|
+
next if [".",".."].include? entry
|
125
|
+
to_queue = (current == "." ? entry : File.join(current, entry))
|
126
|
+
|
127
|
+
queue.push to_queue if FileTest.directory? to_queue
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
queue -= visited
|
132
|
+
visited.push current
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.each_remote_info(dir)
|
137
|
+
self.each_folder(dir) do |folder|
|
138
|
+
filename = File.join(folder, RemoteInfo::FILENAME)
|
139
|
+
yield filename if FileTest.exists? filename
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class ScpUtils
|
145
|
+
def self.remote(local, file)
|
146
|
+
user = file.user
|
147
|
+
port = file.port
|
148
|
+
host = file.host
|
149
|
+
path = file.path
|
150
|
+
|
151
|
+
userstring = user ? user + "@" : ""
|
152
|
+
|
153
|
+
remotepath = path
|
154
|
+
remotepath = File.join(remotepath, local) if local && local != "."
|
155
|
+
|
156
|
+
result = "#{userstring}#{host}:#{remotepath}"
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.local(*candidates)
|
160
|
+
candidates.each do |c|
|
161
|
+
return c if c
|
162
|
+
end
|
163
|
+
|
164
|
+
return "."
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.scp(from, to, dir, port=nil)
|
168
|
+
dirstring = dir ? "-r" : ""
|
169
|
+
portstring = port ? "-P " + port : ""
|
170
|
+
|
171
|
+
return "scp #{portstring} #{dirstring} \"#{from}\" \"#{to}\""
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class CmdParser
|
176
|
+
@@data = {}
|
177
|
+
@@bindings = {}
|
178
|
+
|
179
|
+
def self.opt(key)
|
180
|
+
return @@data[key]
|
181
|
+
end
|
182
|
+
|
183
|
+
def self.set(key, value)
|
184
|
+
@@data[key] = value
|
185
|
+
end
|
186
|
+
|
187
|
+
def self.setup(cmd, *args)
|
188
|
+
parser = OptionParser.new do |opts|
|
189
|
+
opts.banner = "Usage: #{cmd} [options] #{args.join " "}"
|
190
|
+
|
191
|
+
@@opts = opts
|
192
|
+
yield opts
|
193
|
+
@@opts = nil
|
194
|
+
|
195
|
+
opts.on("-v", "--verbose", "Writes a lot of information") do
|
196
|
+
CmdParser.set :verbose, true
|
197
|
+
end
|
198
|
+
|
199
|
+
opts.on("-h", "--help", "Prints this help") do
|
200
|
+
puts opts
|
201
|
+
exit
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
parser.parse! ARGV
|
206
|
+
|
207
|
+
arguments = {}
|
208
|
+
for i in 0...args.size
|
209
|
+
arguments[args[i]] = ARGV[i]
|
210
|
+
end
|
211
|
+
|
212
|
+
return arguments
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.autoset_flag(short, long, description, flag, incompatibles=[])
|
216
|
+
@@bindings[flag] = short
|
217
|
+
@@opts.on(short, long, description) do
|
218
|
+
incompatibles.each do |incompatible|
|
219
|
+
CmdParser.assert_not_set incompatible, short, @@bindings[incompatible]
|
220
|
+
end
|
221
|
+
|
222
|
+
CmdParser.set flag, true
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def self.autoset_param(short, long, description, flag, incompatibles=[])
|
227
|
+
@@bindings[flag] = short
|
228
|
+
@@opts.on(short, long, description) do |v|
|
229
|
+
incompatibles.each do |incompatible|
|
230
|
+
CmdParser.assert_not_set incompatible, short, @@bindings[incompatible]
|
231
|
+
end
|
232
|
+
|
233
|
+
CmdParser.set flag, v
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def self.assert
|
238
|
+
error_message = yield
|
239
|
+
if error_message
|
240
|
+
puts error_message
|
241
|
+
exit
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def self.assert_not_set(forbidden_key, actual_param, forbidden_param, message="incompatible commands")
|
246
|
+
if CmdParser.opt(forbidden_key) != nil
|
247
|
+
puts "Do not use #{forbidden_param} with #{actual_param} (#{message}). Aborting."
|
248
|
+
exit
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
class ConsoleRunner
|
254
|
+
def remove_file(file)
|
255
|
+
File.unlink file
|
256
|
+
end
|
257
|
+
|
258
|
+
def username
|
259
|
+
return `echo $USER`.chomp
|
260
|
+
end
|
261
|
+
|
262
|
+
def run(cmd)
|
263
|
+
vputs "Executing command: #{cmd}"
|
264
|
+
stdout, stderr, status = Open3.capture3(cmd)
|
265
|
+
return [stdout, stderr, status]
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
class SimulatorRunner < ConsoleRunner
|
270
|
+
def remove_file(file)
|
271
|
+
puts "SIMULATE: removed #{file}"
|
272
|
+
end
|
273
|
+
|
274
|
+
def run(cmd)
|
275
|
+
puts "SIMULATE: #{cmd}"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def vputs *args
|
280
|
+
puts *args if CmdParser.opt :verbose
|
281
|
+
end
|
282
|
+
|
283
|
+
OS = ConsoleRunner.new
|
284
|
+
# OS = SimulatorRunner.new
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: remotesync
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Simone Scalabrino
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-01-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.8'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.8.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.8'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.8.1
|
33
|
+
description: Sync remote folders using ssh. Supports network namespaces in Linux.
|
34
|
+
email: s.scalabrino9@gmail.com
|
35
|
+
executables:
|
36
|
+
- rrinit
|
37
|
+
- rrpull
|
38
|
+
- rrpush
|
39
|
+
extensions: []
|
40
|
+
extra_rdoc_files: []
|
41
|
+
files:
|
42
|
+
- bin/rrinit
|
43
|
+
- bin/rrpull
|
44
|
+
- bin/rrpush
|
45
|
+
- lib/commons.rb
|
46
|
+
homepage: https://github.com/intersimone999/remotesync
|
47
|
+
licenses:
|
48
|
+
- GPL-3.0
|
49
|
+
metadata: {}
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
requirements: []
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 2.7.3
|
67
|
+
signing_key:
|
68
|
+
specification_version: 4
|
69
|
+
summary: Sync remote folders using ssh
|
70
|
+
test_files: []
|