-
Notifications
You must be signed in to change notification settings - Fork 7
/
syncer
executable file
·135 lines (106 loc) · 3.52 KB
/
syncer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env ruby
require 'osx/foundation'
require 'optparse'
OSX.require_framework '/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework'
include OSX
options = {}
optparse = OptionParser.new do|opts|
# Set a banner, displayed at the top
# of the help screen.
opts.banner = "Usage: #{$0} [options] file1 file2 ..."
# Define the options, and what they do
options[:user] = nil
opts.on( '-u', '--user USER', 'User name for remote host' ) do|user|
options[:user] = user
end
options[:host] = nil
opts.on( '-H', '--host HOST', 'Remote host to connect' ) do|host|
options[:host] = host
end
options[:port] = nil
opts.on( '-p', '--port PORT', 'Remote port to connect' ) do|port|
options[:port] = port
end
options[:dir] = nil
opts.on( '-d', '--directory DIR', 'Base directory on remote host' ) do|dir|
options[:dir] = dir
end
options[:exclude] = nil
opts.on( '-e', '--exclude-paths EXCLUDE', 'File paths to exclude from the sync, separated by spaces' ) do|exclude|
options[:exclude] = exclude
end
options[:follow] = nil
opts.on( '-f', '--follow-symlinks', 'Listen to symlinked directories' ) do
options[:follow] = true
end
options[:remove] = nil
opts.on( '-r', '--delete', 'Remove remote files that have been deleted locally' ) do|remove|
options[:remove] = '--delete'
end
options[:symlink] = '-L'
opts.on( '-s', '--preserve-symlinks', 'Preserve symlinks' ) do
options[:symlink] = '-l'
end
# This displays the help screen, all programs are
# assumed to have this option.
opts.on( '-h', '--help', 'Display this screen' ) do
puts opts
exit
end
end
optparse.parse!
if !options[:user] then
puts "Please provide a user name with option -u USER or --user USER. Run #{$0} --help for more info."
exit
end
if !options[:host] then
puts "Please provide a host name with option -H HOST or --host USER. Run #{$0} --help for more info."
exit
end
if !options[:dir] then
puts "Please provide a remote directory with option -d DIR or --dir DIR. Run #{$0} --help for more info."
exit
end
$exclude = ""
if options[:exclude] then
options[:exclude].split(/ /).each { |excludePath|
$exclude += "--exclude #{excludePath} "
}
end
$d=File.basename Dir.pwd
$locations = [$d];
if options[:follow] then
Dir.glob( File.join('.', '**', '*') ) { |filename|
if (File.symlink?(filename)) then
$locations.push(File.readlink(filename))
end
}
end
if options[:port] then
options[:ssh] = "ssh -p#{options[:port]}"
else
options[:ssh] = "ssh"
end
Dir.chdir '..'
fsevents_cb = proc do |stream, ctx, numEvents, paths, marks, eventIDs|
system "rsync #{options[:symlink]} -C #{options[:remove]} -rt --rsh='#{options[:ssh]}' #{$exclude} '#{$d}' '#{options[:user]}@#{options[:host]}:#{options[:dir]}'"
system "growlnotify -m 'Change detected in #{numEvents} file(s)'"
end
stream = FSEventStreamCreate(
KCFAllocatorDefault,
fsevents_cb,
nil,
$locations,
KFSEventStreamEventIdSinceNow,
1.0,
0)
die "Failed to create the FSEventStream" unless stream
FSEventStreamScheduleWithRunLoop(
stream,
CFRunLoopGetCurrent(),
KCFRunLoopDefaultMode)
die "Failed to start the FSEventStream" unless FSEventStreamStart(stream)
#print "rsync #{options[:symlink]} -C #{options[:remove]} -rt --rsh='#{options[:ssh]}' #{$exclude} '#{$d}' '#{options[:user]}@#{options[:host]}:#{options[:dir]}'"
system "rsync #{options[:symlink]} -C #{options[:remove]} -rt --rsh='#{options[:ssh]}' #{$exclude} '#{$d}' '#{options[:user]}@#{options[:host]}:#{options[:dir]}'"
system "growlnotify -m 'Syncer started'"
CFRunLoopRun()