wow it works even better now
This commit is contained in:
parent
88400268c5
commit
1c379bdbe7
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
Gemfile.lock
|
||||
.DS_Store
|
||||
|
||||
|
4
Gemfile
4
Gemfile
@ -1,6 +1,6 @@
|
||||
source :rubygems
|
||||
gemspec
|
||||
|
||||
gem 'qtbindings'
|
||||
require 'rbconfig'
|
||||
|
||||
case RbConfig::CONFIG['host_os']
|
||||
@ -10,5 +10,3 @@ when /linux/
|
||||
gem 'rb-inotify'
|
||||
end
|
||||
|
||||
gem 'atomic'
|
||||
gem 'thor'
|
||||
|
227
bin/unison-watch
227
bin/unison-watch
@ -1,21 +1,36 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
$: << File.expand_path('../../lib', __FILE__)
|
||||
|
||||
require 'Qt4'
|
||||
require 'thread'
|
||||
require 'atomic'
|
||||
require 'thor'
|
||||
|
||||
require 'unison/profile'
|
||||
require 'unison/config'
|
||||
require 'unison/bridge'
|
||||
require 'unison/filesystem_watcher'
|
||||
require 'unison/ui/icon'
|
||||
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)
|
||||
|
||||
@profiles = profiles
|
||||
@config = Unison::Config.ensure(File.expand_path('~/.unison/watch.yml'))
|
||||
@queue = Atomic.new([])
|
||||
|
||||
@sync_now = false
|
||||
@ -28,130 +43,50 @@ class UnisonWatcher < Qt::Application
|
||||
end
|
||||
|
||||
def processed_profiles
|
||||
@processed_profiles ||= Unison::Profile.process(@profiles)
|
||||
@processed_profiles ||= Unison::Profile.process(profiles)
|
||||
end
|
||||
|
||||
def watch
|
||||
require 'rbconfig'
|
||||
|
||||
watcher = Thread.new do
|
||||
while !Thread.current[:app]; sleep 0.1; end
|
||||
|
||||
begin
|
||||
@watch = nil
|
||||
|
||||
case RbConfig::CONFIG['host_os']
|
||||
when /darwin/
|
||||
require 'rb-fsevent'
|
||||
@watch = FSEvent.new
|
||||
@watch.watch Thread.current[:paths], :latency => 0.1 do |directories|
|
||||
Thread.current[:app] << directories
|
||||
end
|
||||
when /linux/
|
||||
require 'rb-inotify'
|
||||
@watch = INotify::Notifier.new
|
||||
Thread.current[:paths].each do |path|
|
||||
FileUtils.mkdir_p path
|
||||
|
||||
@watch.watch path, :recursive, :modify, :create, :delete do |event|
|
||||
Thread.current[:app] << event.absolute_name
|
||||
end
|
||||
end
|
||||
Unison::FilesystemWatcher.new(paths_to_watch, self)
|
||||
end
|
||||
|
||||
@watch.run
|
||||
rescue => e
|
||||
puts e.message
|
||||
puts e.backtrace.join("\n")
|
||||
exit
|
||||
end
|
||||
def paths_to_watch
|
||||
processed_profiles.collect(&:paths_with_local_root).flatten
|
||||
end
|
||||
|
||||
watcher[:paths] = processed_profiles.collect(&:paths_with_local_root).flatten
|
||||
watcher[:app] = self
|
||||
end
|
||||
|
||||
def update_status(status)
|
||||
new_status = Qt::Action.new(status, @menu)
|
||||
new_status.enabled = false
|
||||
@menu.insertAction(@active_status, new_status)
|
||||
@menu.removeAction(@status)
|
||||
|
||||
@status = new_status
|
||||
def fileview
|
||||
@fileview ||= Unison::UI::FileView.new(File.expand_path(TRANSFER_LOG))
|
||||
end
|
||||
|
||||
def menu
|
||||
@menu = Qt::Menu.new
|
||||
return @menu if @menu
|
||||
|
||||
@current_text = 'Unison watch idle.'
|
||||
@menu = Unison::UI::Menu.new
|
||||
|
||||
@status = Qt::Action.new(@status_text, @menu)
|
||||
@status.enabled = false
|
||||
|
||||
sync_now = Qt::Action.new("Sync now", @menu)
|
||||
sync_now.connect(SIGNAL :triggered) { @sync_now = true }
|
||||
|
||||
@active_status = Qt::Action.new("Pause syncing", @menu)
|
||||
@active_status.connect(SIGNAL :triggered) { toggle_status }
|
||||
|
||||
@current_log_size = File.size(File.expand_path(TRANSFER_LOG))
|
||||
|
||||
@fileview = Qt::TextEdit.new
|
||||
@fileview.plainText = "Watching for changes..."
|
||||
@fileview.readOnly = true
|
||||
@fileview.resize 800, 600
|
||||
@fileview.connect(SIGNAL :textChanged) { @fileview.moveCursor Qt::TextCursor::End }
|
||||
|
||||
@log = Qt::Action.new("View transfer log", @menu)
|
||||
@log.connect(SIGNAL :triggered) { @fileview.show }
|
||||
|
||||
quit = Qt::Action.new("Quit", @menu)
|
||||
quit.connect(SIGNAL :triggered) { @exiting = true }
|
||||
|
||||
@menu.addAction @active_status
|
||||
@menu.addAction sync_now
|
||||
@menu.addSeparator
|
||||
@menu.addAction @log
|
||||
@menu.addAction quit
|
||||
|
||||
@current_text = 'Unison watch idle.'
|
||||
update_status @current_text
|
||||
@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
|
||||
if @current_icon != @prior_icon
|
||||
if !@icons[@current_icon]
|
||||
@icons[@current_icon] = Qt::Icon.new(File.expand_path("../../assets/#{@current_icon}.png", __FILE__))
|
||||
@icons["large-#{@current_icon}"] = Qt::Icon.new(File.expand_path("../../assets/large-#{@current_icon}.png", __FILE__))
|
||||
end
|
||||
|
||||
@icon.icon = @icons[@current_icon]
|
||||
self.windowIcon = @icons["large-#{@current_icon}"]
|
||||
@icon.toolTip = "Unison Agent\nUsing #{@profiles.join(', ')} profile"
|
||||
if !@prior_icon
|
||||
@icon.show
|
||||
end
|
||||
|
||||
@prior_icon = @current_icon
|
||||
end
|
||||
|
||||
if @current_text!= @prior_text
|
||||
update_status @current_text
|
||||
|
||||
@prior_text = @current_text
|
||||
end
|
||||
@icon.current_icon = @current_icon
|
||||
@menu.status_text = @current_text
|
||||
|
||||
processEvents
|
||||
end
|
||||
|
||||
def ui
|
||||
@icon = Qt::SystemTrayIcon.new
|
||||
@icon.contextMenu = menu
|
||||
@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_icon = nil
|
||||
@prior_text = nil
|
||||
|
||||
@icons = {}
|
||||
@ -168,12 +103,36 @@ class UnisonWatcher < Qt::Application
|
||||
end
|
||||
|
||||
def start
|
||||
self.objectName = "cats"
|
||||
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)
|
||||
@ -183,39 +142,13 @@ class UnisonWatcher < Qt::Application
|
||||
|
||||
@done = false
|
||||
|
||||
runner = Thread.new do
|
||||
@profiles.each do |profile|
|
||||
system %{bash -c 'unison -log -logfile #{TRANSFER_LOG} -batch #{profile}'}
|
||||
end
|
||||
@done = true
|
||||
end
|
||||
Unison::Bridge.run(profiles, TRANSFER_LOG) { @done = true }
|
||||
|
||||
index = 0
|
||||
while !@done
|
||||
@current_icon = "working-#{index + 1}"
|
||||
File.open(File.expand_path(TRANSFER_LOG), 'r') { |fh|
|
||||
fh.seek(@current_log_size)
|
||||
@fileview.plainText = fh.read
|
||||
}
|
||||
|
||||
update_ui
|
||||
|
||||
break if @done
|
||||
|
||||
sleep 0.25
|
||||
index = (index + 1) % 2
|
||||
end
|
||||
|
||||
@current_icon = 'idle'
|
||||
show_working
|
||||
|
||||
@remote_sync_check = SYNC_CHECK_COUNT
|
||||
@sync_now = false
|
||||
@queue.update { [] }
|
||||
|
||||
File.open(File.expand_path(TRANSFER_LOG), 'r') { |fh|
|
||||
fh.seek(@current_log_size)
|
||||
@fileview.plainText = fh.read
|
||||
}
|
||||
end
|
||||
rescue => e
|
||||
puts e.message
|
||||
@ -237,12 +170,15 @@ class UnisonWatcher < Qt::Application
|
||||
def toggle_status(set = nil)
|
||||
@active = set || !@active
|
||||
|
||||
@active_status.text = @active ? "Pause syncing" : "Resume syncing"
|
||||
@menu.active_status_text = @active ? "Pause syncing" : "Resume syncing"
|
||||
@current_icon = @active ? 'idle' : 'paused'
|
||||
end
|
||||
end
|
||||
|
||||
class UnisonCLI < Thor
|
||||
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
|
||||
@ -253,7 +189,32 @@ class UnisonCLI < Thor
|
||||
def method_missing(*args)
|
||||
start(*args)
|
||||
end
|
||||
|
||||
def self.source_root
|
||||
File.expand_path('../../skel', __FILE__)
|
||||
end
|
||||
|
||||
UnisonCLI.start
|
||||
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
|
||||
|
||||
|
28
lib/unison/bridge.rb
Normal file
28
lib/unison/bridge.rb
Normal file
@ -0,0 +1,28 @@
|
||||
module Unison
|
||||
class Bridge
|
||||
def self.run(*args, &block)
|
||||
new(*args).run(&block)
|
||||
end
|
||||
|
||||
def initialize(profiles, log)
|
||||
@profiles, @log = profiles, log
|
||||
end
|
||||
|
||||
def run(&block)
|
||||
Thread.new do
|
||||
begin
|
||||
@profiles.each do |profile|
|
||||
system %{bash -c 'unison -log -logfile #{@log} -batch #{profile} 2>>#{@log.stderr} >>#{@log.stdout}'}
|
||||
end
|
||||
|
||||
block.call
|
||||
rescue => e
|
||||
puts e.message
|
||||
puts e.backtrace.join("\n")
|
||||
raise e
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
70
lib/unison/config.rb
Normal file
70
lib/unison/config.rb
Normal file
@ -0,0 +1,70 @@
|
||||
require 'yaml'
|
||||
require 'atomic'
|
||||
|
||||
module Unison
|
||||
class Config
|
||||
def self.ensure(file)
|
||||
if !File.file?(file)
|
||||
File.open(file, 'wb') { |fh| fh.print YAML.dump(skel_data) }
|
||||
end
|
||||
|
||||
new(file)
|
||||
end
|
||||
|
||||
def self.skel_data
|
||||
{ 'profiles' => [] }
|
||||
end
|
||||
|
||||
def set_profile(profile, is_set)
|
||||
@data.update do |d|
|
||||
if is_set
|
||||
d['profiles'] << profile
|
||||
else
|
||||
d['profiles'].delete(profile)
|
||||
end
|
||||
|
||||
d['profiles'].uniq!
|
||||
|
||||
d
|
||||
end
|
||||
|
||||
@on_update.call if @on_update
|
||||
|
||||
save
|
||||
end
|
||||
|
||||
def on_update(&block)
|
||||
@on_update = block
|
||||
end
|
||||
|
||||
def initialize(file)
|
||||
@file = file
|
||||
|
||||
@data = Atomic.new(nil)
|
||||
end
|
||||
|
||||
def active?(profile)
|
||||
profiles.include?(profile)
|
||||
end
|
||||
|
||||
def profiles
|
||||
data['profiles']
|
||||
end
|
||||
|
||||
def data
|
||||
@data.update { |d| d || YAML.load_file(@file) }
|
||||
@data.value
|
||||
end
|
||||
|
||||
def active_profiles?
|
||||
!profiles.empty?
|
||||
end
|
||||
|
||||
def save
|
||||
@data.update do |d|
|
||||
File.open(@file, 'wb') { |fh| fh.print YAML.dump(d) }
|
||||
d
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
58
lib/unison/filesystem_watcher.rb
Normal file
58
lib/unison/filesystem_watcher.rb
Normal file
@ -0,0 +1,58 @@
|
||||
module Unison
|
||||
class FilesystemWatcher
|
||||
class NoWatcherAvailable < StandardError ; end
|
||||
|
||||
def initialize(paths, owner)
|
||||
@paths, @owner = paths, owner
|
||||
end
|
||||
|
||||
def run
|
||||
require 'rbconfig'
|
||||
|
||||
@watcher = Thread.new do
|
||||
while !Thread.current[:app]; sleep 0.1; end
|
||||
|
||||
begin
|
||||
case RbConfig::CONFIG['host_os']
|
||||
when /(darwin|linux)/
|
||||
@watch = send("watcher_for_#{$1}")
|
||||
else
|
||||
raise NoWatcherAvailable.new
|
||||
end
|
||||
|
||||
@watch.run
|
||||
rescue => e
|
||||
puts e.message
|
||||
puts e.backtrace.join("\n")
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
@watcher[:paths] = @paths
|
||||
@watcher[:app] = @owner
|
||||
end
|
||||
|
||||
def watcher_for_darwin
|
||||
require 'rb-fsevent'
|
||||
watch = FSEvent.new
|
||||
watch.watch Thread.current[:paths], :latency => 1.0 do |directories|
|
||||
Thread.current[:app] << directories
|
||||
end
|
||||
watch
|
||||
end
|
||||
|
||||
def watcher_for_linux
|
||||
require 'rb-inotify'
|
||||
watch = INotify::Notifier.new
|
||||
Thread.current[:paths].each do |path|
|
||||
FileUtils.mkdir_p path
|
||||
|
||||
watch.watch path, :recursive, :modify, :create, :delete do |event|
|
||||
Thread.current[:app] << event.absolute_name
|
||||
end
|
||||
end
|
||||
watch
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,9 +1,15 @@
|
||||
module Unison
|
||||
class Profile
|
||||
PROFILE_DIR = File.expand_path('~/.unison')
|
||||
|
||||
def self.process(profiles)
|
||||
profiles.collect { |profile| new(profile) }
|
||||
end
|
||||
|
||||
def self.available
|
||||
Dir[File.join(PROFILE_DIR, '*.prf')].collect { |file| File.basename(file).gsub('.prf', '') }.sort
|
||||
end
|
||||
|
||||
def initialize(which)
|
||||
@which = which
|
||||
end
|
||||
|
31
lib/unison/ui/fileview.rb
Normal file
31
lib/unison/ui/fileview.rb
Normal file
@ -0,0 +1,31 @@
|
||||
module Unison
|
||||
module UI
|
||||
class FileView < Qt::TextEdit
|
||||
INITIAL = "Watching for changes..."
|
||||
|
||||
def initialize(file, *args)
|
||||
super(*args)
|
||||
|
||||
@file = file
|
||||
@current_log_size = File.size(@file)
|
||||
|
||||
self.plainText = INITIAL
|
||||
self.readOnly = true
|
||||
self.resize 800, 600
|
||||
self.connect(SIGNAL(:textChanged), &method(:on_text_change))
|
||||
end
|
||||
|
||||
def on_text_change
|
||||
self.moveCursor Qt::TextCursor::End
|
||||
end
|
||||
|
||||
def read!
|
||||
File.open(@file, 'r') { |fh|
|
||||
fh.seek(@current_log_size)
|
||||
self.plainText = fh.read
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
45
lib/unison/ui/icon.rb
Normal file
45
lib/unison/ui/icon.rb
Normal file
@ -0,0 +1,45 @@
|
||||
module Unison
|
||||
module UI
|
||||
class Icon < Qt::SystemTrayIcon
|
||||
def initialize(menu, window, profiles, icon_source, *args)
|
||||
super(*args)
|
||||
|
||||
self.contextMenu = menu
|
||||
@window, @icon_source, @profiles = window, icon_source, profiles
|
||||
|
||||
@current_icon = nil
|
||||
@icons = {}
|
||||
end
|
||||
|
||||
def qt_icon_for(name)
|
||||
@icons[name] ||= Qt::Icon.new(File.join(@icon_source, "#{name}.png"))
|
||||
end
|
||||
|
||||
def large_qt_icon_for(name)
|
||||
qt_icon_for("large-#{name}")
|
||||
end
|
||||
|
||||
def profiles=(profiles)
|
||||
@profiles = profiles
|
||||
set_tooltip
|
||||
end
|
||||
|
||||
def current_icon=(icon)
|
||||
if icon != @current_icon
|
||||
self.icon = qt_icon_for(icon)
|
||||
@window.windowIcon = large_qt_icon_for(icon)
|
||||
set_tooltip
|
||||
show if !@current_icon
|
||||
|
||||
@current_icon = icon
|
||||
end
|
||||
end
|
||||
|
||||
def set_tooltip
|
||||
self.toolTip = "Unison Agent\nUsing #{@profiles.join(', ')} profile"
|
||||
show
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
70
lib/unison/ui/menu.rb
Normal file
70
lib/unison/ui/menu.rb
Normal file
@ -0,0 +1,70 @@
|
||||
module Unison
|
||||
module UI
|
||||
class Menu < Qt::Menu
|
||||
IDLE = 'Unison watch idle.'
|
||||
SYNC_NOW = 'Sync now'
|
||||
PAUSE_SYNCING = 'Pause syncing'
|
||||
VIEW_TRANSFER_LOG = "View transfer log"
|
||||
QUIT = 'Quit'
|
||||
|
||||
def initialize(*args)
|
||||
super(*args)
|
||||
|
||||
@status_text = IDLE
|
||||
end
|
||||
|
||||
def on(event, &block)
|
||||
@on ||= {}
|
||||
@on[event] = block
|
||||
end
|
||||
|
||||
def generate
|
||||
generate_status
|
||||
|
||||
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])
|
||||
|
||||
@log = Qt::Action.new(VIEW_TRANSFER_LOG, @menu)
|
||||
@log.connect(SIGNAL(:triggered), &@on[:view_log])
|
||||
|
||||
@preferences = Qt::Action.new('Preferences...', @menu)
|
||||
@preferences.connect(SIGNAL(:triggered), &@on[:preferences])
|
||||
|
||||
quit = Qt::Action.new(QUIT, @menu)
|
||||
quit.connect(SIGNAL(:triggered), &@on[:quit])
|
||||
|
||||
addAction @active_status
|
||||
addAction sync_now
|
||||
addSeparator
|
||||
addAction @log
|
||||
addAction @preferences
|
||||
addAction quit
|
||||
end
|
||||
|
||||
def status_text=(text)
|
||||
if @status_text != text
|
||||
@status_text = text
|
||||
|
||||
generate_status
|
||||
end
|
||||
end
|
||||
|
||||
def active_status_text=(text)
|
||||
@active_status.text = text
|
||||
end
|
||||
|
||||
def generate_status
|
||||
new_status = Qt::Action.new(@status_text, self)
|
||||
new_status.enabled = false
|
||||
insertAction(@active_status, new_status)
|
||||
removeAction(@status)
|
||||
|
||||
@status = new_status
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
32
lib/unison/ui/preferences.rb
Normal file
32
lib/unison/ui/preferences.rb
Normal file
@ -0,0 +1,32 @@
|
||||
module Unison
|
||||
module UI
|
||||
class Preferences < Qt::Widget
|
||||
def initialize(config, *args)
|
||||
super(*args)
|
||||
|
||||
@config = config
|
||||
|
||||
generate
|
||||
end
|
||||
|
||||
def generate
|
||||
layout = Qt::GridLayout.new
|
||||
|
||||
profile_group = Qt::GroupBox.new("Profiles")
|
||||
profile_group_layout = Qt::VBoxLayout.new
|
||||
profile_group.setLayout(profile_group_layout)
|
||||
|
||||
Unison::Profile.available.each do |profile|
|
||||
radio = Qt::CheckBox.new(profile)
|
||||
radio.checked = @config.active?(profile)
|
||||
radio.connect(SIGNAL "toggled(bool)") { |checked| @config.set_profile(profile, checked) }
|
||||
profile_group_layout.addWidget(radio)
|
||||
end
|
||||
|
||||
layout.addWidget(profile_group)
|
||||
|
||||
setLayout(layout)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
24
skel/UnisonWatch.app/Contents/Info.plist
Normal file
24
skel/UnisonWatch.app/Contents/Info.plist
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>UnisonWatch</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>Unison Watch</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>webapps.webrunner</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>UnisonWatch</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.3.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>WRUN</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.0.1.20070616</string>
|
||||
</dict>
|
||||
</plist>
|
5
skel/UnisonWatch.app/Contents/MacOS/UnisonWatch.tt
Executable file
5
skel/UnisonWatch.app/Contents/MacOS/UnisonWatch.tt
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd <%= gem_directory %>
|
||||
GEM_HOME=<%= ENV['GEM_HOME'] %> GEM_PATH=<%= ENV['GEM_PATH'] %> PATH=<%= `which ruby`.gsub(%r{/[^/]+$}, '') %>:$PATH bin/unison-watch
|
||||
|
1
skel/UnisonWatch.app/Contents/PkgInfo
Normal file
1
skel/UnisonWatch.app/Contents/PkgInfo
Normal file
@ -0,0 +1 @@
|
||||
APPLWRUN
|
19
unison-watch.gemspec
Normal file
19
unison-watch.gemspec
Normal file
@ -0,0 +1,19 @@
|
||||
Gem::Specification.new do |gem|
|
||||
gem.authors = ["John Bintz"]
|
||||
gem.email = ["john@coswellproductions.com"]
|
||||
gem.description = %q{No-nonsense JavaScript testing solution.}
|
||||
gem.summary = %q{No-nonsense JavaScript testing solution.}
|
||||
gem.homepage = ""
|
||||
|
||||
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
||||
gem.files = `git ls-files`.split("\n")
|
||||
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
||||
gem.name = "unison-watch"
|
||||
gem.require_paths = ["lib"]
|
||||
gem.version = '0.0.1'
|
||||
|
||||
gem.add_dependency 'qtbindings'
|
||||
gem.add_dependency 'thor'
|
||||
gem.add_dependency 'atomic'
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user