This commit is contained in:
John Bintz 2012-05-08 06:46:10 -04:00
parent 1c379bdbe7
commit 6e291cc583
6 changed files with 222 additions and 208 deletions

View File

@ -5,8 +5,10 @@ $: << File.expand_path('../../lib', __FILE__)
require 'Qt4'
require 'thread'
require 'atomic'
require 'thor'
require 'unison'
require 'unison/watcher'
require 'unison/cli'
require 'unison/profile'
require 'unison/config'
require 'unison/bridge'
@ -16,205 +18,6 @@ require 'unison/ui/menu'
require 'unison/ui/fileview'
require 'unison/ui/preferences'
require 'forwardable'
class UnisonWatcher < Qt::Application
TRANSFER_LOG = '~/unison.log'
SYNC_CHECK_COUNT = 600
SYNC_CHECK_TIME = 0.1
extend Forwardable
def_delegators :@config, :profiles
def initialize(profiles, *args)
super(*args)
@config = Unison::Config.ensure(File.expand_path('~/.unison/watch.yml'))
@queue = Atomic.new([])
@sync_now = false
@exiting = false
@active = true
end
def <<(dirs)
@queue.update { |q| q += [ dirs ].flatten ; q }
end
def processed_profiles
@processed_profiles ||= Unison::Profile.process(profiles)
end
def watch
Unison::FilesystemWatcher.new(paths_to_watch, self)
end
def paths_to_watch
processed_profiles.collect(&:paths_with_local_root).flatten
end
def fileview
@fileview ||= Unison::UI::FileView.new(File.expand_path(TRANSFER_LOG))
end
def menu
return @menu if @menu
@menu = Unison::UI::Menu.new
@menu.on(:sync_now) { @sync_now = true }
@menu.on(:toggle_status) { toggle_status }
@menu.on(:view_log) { fileview.show }
@menu.on(:quit) { @exiting = true }
@menu.on(:preferences) { preferences.show }
@menu.generate
@menu
end
def update_ui
@icon.current_icon = @current_icon
@menu.status_text = @current_text
processEvents
end
def ui
@icon = Unison::UI::Icon.new(menu, self, profiles, File.expand_path('../../assets', __FILE__))
@config.on_update { @icon.profiles = @config.profiles }
@current_icon = 'idle'
toggle_status true
@prior_text = nil
@icons = {}
@remote_sync_check = SYNC_CHECK_COUNT
while !@exiting
check
update_ui
sleep SYNC_CHECK_TIME
end
end
def start
if !@config.active_profiles?
preferences.show
end
watch
ui
end
def preferences
@preferences ||= Unison::UI::Preferences.new(@config)
end
def show_working
index = 0
while !@done
@current_icon = "working-#{index + 1}"
fileview.read!
update_ui
break if @done
sleep 0.25
index = (index + 1) % 2
end
@current_icon = 'idle'
fileview.read!
end
def check
begin
if @active && (@queue.value.length > 0 || @remote_sync_check == 0 || @sync_now)
dir = nil
@current_text = "Syncing..."
@done = false
Unison::Bridge.run(profiles, TRANSFER_LOG) { @done = true }
show_working
@remote_sync_check = SYNC_CHECK_COUNT
@sync_now = false
@queue.update { [] }
end
rescue => e
puts e.message
puts e.backtrace.join("\n")
exit
end
@remote_sync_check -= 1
if @active
@current_text = "Next check in #{sprintf("%.0d", SYNC_CHECK_TIME * @remote_sync_check)} secs."
else
@current_text = "Syncing paused."
@remote_sync_check = SYNC_CHECK_COUNT
end
end
def toggle_status(set = nil)
@active = set || !@active
@menu.active_status_text = @active ? "Pause syncing" : "Resume syncing"
@current_icon = @active ? 'idle' : 'paused'
end
end
module Unison
class CLI < Thor
include Thor::Actions
desc 'start profile <profile> ...', 'Run Unison Watch using the provided profiles'
def start(*profiles)
UnisonWatcher.new(profiles, ARGV).start
end
default_task :run
def method_missing(*args)
start(*args)
end
def self.source_root
File.expand_path('../../skel', __FILE__)
end
desc 'app-bundle', 'Make an app bundle in the current directory'
def app_bundle
destination_path = Dir.pwd
directory 'UnisonWatch.app', 'UnisonWatch.app'
Dir['UnisonWatch.app/**/*'].each do |file|
if File.directory?(file)
File.chmod(0755, file)
end
end
File.chmod(0755, "UnisonWatch.app/Contents/MacOS/UnisonWatch")
end
no_tasks do
def gem_directory
File.expand_path('../..', __FILE__)
end
end
end
end
Unison::CLI.start

6
lib/unison.rb Normal file
View File

@ -0,0 +1,6 @@
module Unison
class << self
def root ; File.expand_path('../..', __FILE__) ; end
end
end

View File

@ -12,14 +12,15 @@ module Unison
Thread.new do
begin
@profiles.each do |profile|
system %{bash -c 'unison -log -logfile #{@log} -batch #{profile} 2>>#{@log.stderr} >>#{@log.stdout}'}
#system %{bash -c 'unison -log -logfile #{@log} -batch #{profile} 2>>#{@log}.stderr >>#{@log}.stdout'}
system %{bash -c 'unison -log -logfile #{@log} -batch #{profile}'}
end
block.call
rescue => e
puts e.message
puts e.backtrace.join("\n")
raise e
exit 1
end
end
end

41
lib/unison/cli.rb Normal file
View File

@ -0,0 +1,41 @@
require 'thor'
module Unison
class CLI < Thor
include Thor::Actions
desc 'start profile <profile> ...', 'Run Unison Watch using the provided profiles'
def start(*profiles)
Watcher.new(profiles, ARGV).start
end
default_task :run
def method_missing(*args)
start(*args)
end
def self.source_root
File.join(Unison.root, 'skel')
end
desc 'app-bundle', 'Make an app bundle in the current directory'
def app_bundle
destination_path = Dir.pwd
directory 'UnisonWatch.app', 'UnisonWatch.app'
Dir['UnisonWatch.app/**/*'].each do |file|
if File.directory?(file)
File.chmod(0755, file)
end
end
File.chmod(0755, "UnisonWatch.app/Contents/MacOS/UnisonWatch")
end
no_tasks do
def gem_directory
Unison.root
end
end
end
end

View File

@ -21,8 +21,8 @@ module Unison
def generate
generate_status
sync_now = Qt::Action.new(SYNC_NOW, self)
sync_now.connect(SIGNAL(:triggered), &@on[:sync_now])
@sync_now = Qt::Action.new(SYNC_NOW, self)
@sync_now.connect(SIGNAL(:triggered), &@on[:sync_now])
@active_status = Qt::Action.new(PAUSE_SYNCING, self)
@active_status.connect(SIGNAL(:triggered), &@on[:toggle_status])
@ -33,15 +33,15 @@ module Unison
@preferences = Qt::Action.new('Preferences...', @menu)
@preferences.connect(SIGNAL(:triggered), &@on[:preferences])
quit = Qt::Action.new(QUIT, @menu)
quit.connect(SIGNAL(:triggered), &@on[:quit])
@quit = Qt::Action.new(QUIT, @menu)
@quit.connect(SIGNAL(:triggered), &@on[:quit])
addAction @active_status
addAction sync_now
addAction @sync_now
addSeparator
addAction @log
addAction @preferences
addAction quit
addAction @quit
end
def status_text=(text)

163
lib/unison/watcher.rb Normal file
View File

@ -0,0 +1,163 @@
require 'forwardable'
module Unison
class Watcher < Qt::Application
TRANSFER_LOG = '~/unison.log'
SYNC_CHECK_COUNT = 600
SYNC_CHECK_TIME = 0.1
extend Forwardable
def_delegators :@config, :profiles
def initialize(profiles, *args)
super(*args)
@config = Unison::Config.ensure(File.expand_path('~/.unison/watch.yml'))
@queue = Atomic.new([])
@sync_now = false
@exiting = false
@active = true
end
def <<(dirs)
@queue.update { |q| q += [ dirs ].flatten ; q }
end
def processed_profiles
@processed_profiles ||= Unison::Profile.process(profiles)
end
def watch
Unison::FilesystemWatcher.new(paths_to_watch, self)
end
def paths_to_watch
processed_profiles.collect(&:paths_with_local_root).flatten
end
def fileview
@fileview ||= Unison::UI::FileView.new(File.expand_path(TRANSFER_LOG))
end
def menu
return @menu if @menu
@menu = Unison::UI::Menu.new
@menu.on(:sync_now) { @sync_now = true }
@menu.on(:toggle_status) { toggle_status }
@menu.on(:view_log) { fileview.show }
@menu.on(:quit) { @exiting = true }
@menu.on(:preferences) { preferences.show }
@menu.generate
@menu
end
def update_ui
@icon.current_icon = @current_icon
@menu.status_text = @current_text
processEvents
end
def ui
@icon = Unison::UI::Icon.new(menu, self, profiles, File.join(Unison.root, 'assets'))
@config.on_update { @icon.profiles = @config.profiles }
@current_icon = 'idle'
toggle_status true
@prior_text = nil
@icons = {}
@remote_sync_check = SYNC_CHECK_COUNT
while !@exiting
check
update_ui
sleep SYNC_CHECK_TIME
end
end
def start
if !@config.active_profiles?
preferences.show
end
watch
ui
end
def preferences
@preferences ||= Unison::UI::Preferences.new(@config)
end
def show_working
index = 0
while true do
@current_icon = "working-#{index + 1}"
fileview.read!
update_ui
break if @done or @exiting
sleep 0.25
index = (index + 1) % 2
end
@current_icon = current_icon
fileview.read!
end
def check
begin
if @active && (@queue.value.length > 0 || @remote_sync_check == 0 || @sync_now)
dir = nil
@current_text = "Syncing..."
@done = false
Unison::Bridge.run(profiles, TRANSFER_LOG) { @done = true }
show_working
@remote_sync_check = SYNC_CHECK_COUNT
@sync_now = false
@queue.update { [] }
end
rescue => e
puts e.message
puts e.backtrace.join("\n")
exit 1
end
@remote_sync_check -= 1
if @active
@current_text = "Next check in #{sprintf("%.0d", SYNC_CHECK_TIME * @remote_sync_check)} secs."
else
@current_text = "Syncing paused."
@remote_sync_check = SYNC_CHECK_COUNT
end
end
def toggle_status(set = nil)
@active = set || !@active
@menu.active_status_text = @active ? "Pause syncing" : "Resume syncing"
@current_icon = current_icon
end
def current_icon
@active ? 'idle' : 'paused'
end
end
end