Created
April 20, 2012 05:57
-
-
Save lox/2426455 to your computer and use it in GitHub Desktop.
Watch a local folder and synchronize it with a remote folder over SCP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'rubygems' | |
require 'rb-fsevent' | |
require 'optparse' | |
require 'net/ssh' | |
require 'net/sftp' | |
def watch_directory(sftp, watch_dir, target_dir) | |
fsevent = FSEvent.new | |
fsevent.watch [watch_dir] do |directories| | |
directories.each do |dir| | |
unless dir.include? ".git" | |
sync_directory sftp, dir, dir.gsub(watch_dir, target_dir) | |
end | |
end | |
end | |
fsevent.run | |
end | |
def sync_directory(sftp, local_dir, remote_dir) | |
remote_files = {} | |
# collect remote mtimes | |
sftp.dir.foreach remote_dir do |f| | |
remote_files[f.name] = f.attributes.mtime | |
end | |
# check local mtimes | |
Dir.foreach(local_dir) do |local_file| | |
f = "#{local_dir}#{local_file}" | |
if File.file?(f) and (!remote_files.key? local_file or remote_files[local_file] < File.mtime(f).to_i) | |
print "#{f} changed, sending... " | |
timer = Time.now | |
begin | |
sftp.upload! f, "#{remote_dir}#{local_file}" | |
puts " done in #{(Time.now - timer)*1000}ms" | |
rescue Exception => e | |
puts " failed! #{e.message}" | |
end | |
end | |
end | |
end | |
options = { :verbose=>false, :git=>false } | |
OptionParser.new do |opts| | |
opts.banner = "Usage: watch.rb user@host:path [options]" | |
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v| | |
options[:verbose] = v | |
end | |
opts.on("-g", "--git", "Sync the remote side to the current git HEAD") do |g| | |
options[:git] = g | |
end | |
end.parse! | |
remote_user = ARGV[0].split('@').first | |
remote_host = ARGV[0].split('@').last.split(':').first | |
watch_dir = File.expand_path(ARGV[0].split('@').last.split(':').last) | |
remote_dir = "/home/#{remote_user}/"+File.basename(watch_dir) | |
Net::SSH.start(remote_host, remote_user) do |session| | |
if options[:git] | |
branch = `cd #{watch_dir}; git name-rev --name-only HEAD`.chomp | |
sha1 = `cd #{watch_dir}; git rev-parse HEAD`.chomp | |
puts "Cleaning remote repo" | |
session.exec! "git clean -d #{remote_dir}" | |
puts "Synchronizing remote to #{branch}@#{sha1}" | |
["git fetch", "git checkout #{branch}", "git reset --hard #{sha1}", "git submodule update --init"].each do |c| | |
session.exec! "cd #{remote_dir}; #{c}" | |
end | |
puts "Sending changed files from local repo" | |
puts `cd #{watch_dir}; git status -s -u --ignore-submodules`.chomp | |
end | |
puts "Listening for changes in #{watch_dir}" | |
watch_directory session.sftp, watch_dir, remote_dir | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment