vcs 0.1 → 0.2.148
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.
- data/Rakefile +17 -3
- data/bin/vcs +57 -34
- data/doc/jamis.rb +564 -0
- data/ruby_ex/abstract.rb +254 -0
- data/ruby_ex/abstract_node.rb +85 -0
- data/ruby_ex/algorithms/simulated_annealing.rb +140 -0
- data/ruby_ex/array_each_pair.rb +18 -0
- data/ruby_ex/ask.rb +101 -0
- data/ruby_ex/attributed_class.rb +302 -0
- data/ruby_ex/cache.rb +373 -0
- data/ruby_ex/checkout.rb +12 -0
- data/ruby_ex/choose.rb +271 -0
- data/ruby_ex/commands.rb +18 -0
- data/ruby_ex/commands/command.rb +401 -0
- data/ruby_ex/commands/datas.rb +16 -0
- data/ruby_ex/commands/datas/data.rb +33 -0
- data/ruby_ex/commands/datas/factory.rb +66 -0
- data/ruby_ex/commands/factory.rb +66 -0
- data/ruby_ex/commands/helpers.rb +67 -0
- data/ruby_ex/commands/pipe.rb +64 -0
- data/ruby_ex/commands/runners.rb +17 -0
- data/ruby_ex/commands/runners/exec.rb +49 -0
- data/ruby_ex/commands/runners/fork.rb +97 -0
- data/ruby_ex/commands/runners/runner.rb +107 -0
- data/ruby_ex/commands/seq.rb +27 -0
- data/ruby_ex/config_file.rb +96 -0
- data/ruby_ex/const_regexp.rb +59 -0
- data/ruby_ex/daemon.rb +134 -0
- data/ruby_ex/diff.rb +667 -0
- data/ruby_ex/dlogger.rb +62 -0
- data/ruby_ex/drb/dispatcher.rb +252 -0
- data/ruby_ex/drb/dispatcher_server_test.rb +29 -0
- data/ruby_ex/drb/drb_observable.rb +97 -0
- data/ruby_ex/drb/drb_observable_pool.rb +27 -0
- data/ruby_ex/drb/drb_service.rb +43 -0
- data/ruby_ex/drb/drb_undumped_attributes.rb +55 -0
- data/ruby_ex/drb/drb_undumped_indexed_object.rb +54 -0
- data/ruby_ex/drb/insecure_protected_methods.rb +103 -0
- data/ruby_ex/drb/session_client_test.rb +40 -0
- data/ruby_ex/drb/session_manager.rb +246 -0
- data/ruby_ex/drb/session_server.rb +53 -0
- data/ruby_ex/dtime.rb +143 -0
- data/ruby_ex/dumpable_proc.rb +63 -0
- data/ruby_ex/exception.rb +32 -0
- data/ruby_ex/filetype.rb +229 -0
- data/ruby_ex/fileutils_ex.rb +44 -0
- data/ruby_ex/fold.rb +58 -0
- data/ruby_ex/generate_id.rb +44 -0
- data/ruby_ex/hookable.rb +262 -0
- data/ruby_ex/hooker.rb +54 -0
- data/ruby_ex/inactive_timeout.rb +137 -0
- data/ruby_ex/indexed_node.rb +66 -0
- data/ruby_ex/io_marshal.rb +100 -0
- data/ruby_ex/ioo.rb +194 -0
- data/ruby_ex/labeled_node.rb +63 -0
- data/ruby_ex/logger_observer.rb +23 -0
- data/ruby_ex/md5sum.rb +66 -0
- data/ruby_ex/mktemp.rb +208 -0
- data/ruby_ex/module/attr_once.rb +36 -0
- data/ruby_ex/module/autoload_tree.rb +75 -0
- data/ruby_ex/module/hierarchy.rb +335 -0
- data/ruby_ex/module/instance_method_visibility.rb +73 -0
- data/ruby_ex/module_ex.rb +11 -0
- data/ruby_ex/node.rb +80 -0
- data/ruby_ex/object_monitor.rb +145 -0
- data/ruby_ex/object_monitor_activity.rb +33 -0
- data/ruby_ex/observable.rb +140 -0
- data/ruby_ex/observable_pool.rb +293 -0
- data/ruby_ex/orderedhash.rb +252 -0
- data/ruby_ex/pathname_ex.rb +152 -0
- data/ruby_ex/pp_hierarchy.rb +29 -0
- data/ruby_ex/pseudo_cache.rb +190 -0
- data/ruby_ex/queue.rb +56 -0
- data/ruby_ex/random_generators.rb +25 -0
- data/ruby_ex/random_generators/random_generator.rb +31 -0
- data/ruby_ex/random_generators/ruby.rb +23 -0
- data/ruby_ex/safe_eval.rb +348 -0
- data/ruby_ex/sendmail.rb +215 -0
- data/ruby_ex/service_manager.rb +121 -0
- data/ruby_ex/session/administrable.rb +120 -0
- data/ruby_ex/session/client.rb +153 -0
- data/ruby_ex/session/const.rb +18 -0
- data/ruby_ex/session/dispatcher.rb +184 -0
- data/ruby_ex/session/error.rb +21 -0
- data/ruby_ex/session/fetchable.rb +57 -0
- data/ruby_ex/session/fetcher.rb +62 -0
- data/ruby_ex/session/hookable.rb +26 -0
- data/ruby_ex/session/profile.rb +110 -0
- data/ruby_ex/session/server.rb +582 -0
- data/ruby_ex/session/test/administrable_test.rb +337 -0
- data/ruby_ex/session/test/basic_test.rb +523 -0
- data/ruby_ex/session/test/dispatcher_test.rb +409 -0
- data/ruby_ex/session/test/fetchable_test.rb +119 -0
- data/ruby_ex/session/test/sub_server_test.rb +188 -0
- data/ruby_ex/shuffle.rb +30 -0
- data/ruby_ex/spring.rb +136 -0
- data/ruby_ex/spring_set.rb +137 -0
- data/ruby_ex/string_ex.rb +28 -0
- data/ruby_ex/symtbl.rb +106 -0
- data/ruby_ex/synflow.rb +474 -0
- data/ruby_ex/test/unit/ui/yaml/testrunner.rb +164 -0
- data/ruby_ex/thread_mutex.rb +10 -0
- data/ruby_ex/timeout_ex.rb +81 -0
- data/ruby_ex/top_down.rb +73 -0
- data/ruby_ex/trace.rb +26 -0
- data/ruby_ex/uri/druby.rb +81 -0
- data/ruby_ex/uri/file.rb +65 -0
- data/ruby_ex/uri/ftp_ex.rb +37 -0
- data/ruby_ex/uri/http_ex.rb +43 -0
- data/ruby_ex/uri/ssh.rb +92 -0
- data/ruby_ex/uri/svn.rb +118 -0
- data/ruby_ex/uri_ex.rb +45 -0
- data/ruby_ex/verbose_object.rb +30 -0
- data/ruby_ex/version.rb +66 -0
- data/ruby_ex/yaml/basenode_ext.rb +63 -0
- data/ruby_ex/yaml/chop_header.rb +23 -0
- data/ruby_ex/yaml/transform.rb +449 -0
- data/ruby_ex/yaml/yregexpath.rb +76 -0
- data/src/changelog.rb +28 -18
- data/src/conflict.rb +20 -0
- data/src/diff.rb +18 -0
- data/src/diffstat.rb +9 -3
- data/src/last_changed_date.rb +18 -0
- data/src/mail.rb +33 -65
- data/src/message.rb +15 -9
- data/src/mycommit.rb +29 -14
- data/src/news.rb +24 -3
- data/src/status.rb +17 -0
- data/src/svn.rb +2 -2
- data/src/vcs.rb +24 -3
- metadata +124 -5
- data/lrdetools.rb +0 -12
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
|
|
2
|
+
# Author: Nicolas Despres <polrop@lrde.epita.fr>.
|
|
3
|
+
# License: Gnu General Public License.
|
|
4
|
+
|
|
5
|
+
# $LastChangedBy: polrop $
|
|
6
|
+
# $Id: object_monitor.rb 105 2005-01-16 17:42:26Z polrop $
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
require 'observable'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ObjectMonitor
|
|
13
|
+
include Observable
|
|
14
|
+
|
|
15
|
+
attr_reader :nb_method
|
|
16
|
+
|
|
17
|
+
def initialize(object, *observers)
|
|
18
|
+
@object = object
|
|
19
|
+
add_observers(*observers)
|
|
20
|
+
@nb_method = 0
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def method_missing(meth, *args, &block)
|
|
24
|
+
info = init_method_info(meth, *args, &block)
|
|
25
|
+
start_method(info)
|
|
26
|
+
result = nil
|
|
27
|
+
begin
|
|
28
|
+
result = @object.send(meth, *args, &block)
|
|
29
|
+
rescue Exception => exc
|
|
30
|
+
info[:stop_time] = Time.now
|
|
31
|
+
info[:error] = exc
|
|
32
|
+
stop_method(info)
|
|
33
|
+
raise exc
|
|
34
|
+
ensure
|
|
35
|
+
@nb_method += 1
|
|
36
|
+
end
|
|
37
|
+
info[:stop_time] = Time.now
|
|
38
|
+
info[:result] = result
|
|
39
|
+
stop_method(info)
|
|
40
|
+
result
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
protected
|
|
44
|
+
def init_method_info(meth, *args, &block)
|
|
45
|
+
{
|
|
46
|
+
:num => @nb_method,
|
|
47
|
+
:receiver => @object,
|
|
48
|
+
:method => meth,
|
|
49
|
+
:args => args,
|
|
50
|
+
:block => block,
|
|
51
|
+
:start_time => Time.now,
|
|
52
|
+
:stop_time => nil,
|
|
53
|
+
:thread => Thread.current,
|
|
54
|
+
:error => nil,
|
|
55
|
+
:result => nil,
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
protected
|
|
60
|
+
def start_method(info)
|
|
61
|
+
changed
|
|
62
|
+
notify_observers(:start_method, info)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
protected
|
|
66
|
+
def stop_method(info)
|
|
67
|
+
changed
|
|
68
|
+
notify_observers(:stop_method, info)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end # class ObjectMonitor
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
if defined? TEST_MODE or __FILE__ == $0
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
require 'test/unit/ui/yaml/testrunner'
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class ObjectMonitorTest < Test::Unit::TestCase
|
|
81
|
+
|
|
82
|
+
class Foo
|
|
83
|
+
|
|
84
|
+
def hello
|
|
85
|
+
'hello'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def failed
|
|
89
|
+
raise 'failed msg'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class Obsv
|
|
95
|
+
|
|
96
|
+
attr_reader :last_msg
|
|
97
|
+
|
|
98
|
+
def initialize
|
|
99
|
+
@last_msg = []
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def update(*args)
|
|
103
|
+
@last_msg << args
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def test_normal
|
|
109
|
+
f = Foo.new
|
|
110
|
+
obsv = Obsv.new
|
|
111
|
+
fm = ObjectMonitor.new(f, obsv)
|
|
112
|
+
assert_equal(0, fm.nb_method)
|
|
113
|
+
assert_equal([], obsv.last_msg)
|
|
114
|
+
assert_equal('hello', fm.hello)
|
|
115
|
+
assert_equal(1, fm.nb_method)
|
|
116
|
+
assert_equal(:start_method, obsv.last_msg[0][0])
|
|
117
|
+
assert_equal(2, obsv.last_msg[0].size)
|
|
118
|
+
assert_equal(:stop_method, obsv.last_msg[1][0])
|
|
119
|
+
assert_equal(2, obsv.last_msg[0].size)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def test_exception
|
|
123
|
+
f = Foo.new
|
|
124
|
+
obsv = Obsv.new
|
|
125
|
+
fm = ObjectMonitor.new(f, obsv)
|
|
126
|
+
assert_equal(0, fm.nb_method)
|
|
127
|
+
assert_equal([], obsv.last_msg)
|
|
128
|
+
assert_raises(RuntimeError) { fm.failed }
|
|
129
|
+
assert_equal(1, fm.nb_method)
|
|
130
|
+
assert_equal(:start_method, obsv.last_msg[0][0])
|
|
131
|
+
assert_equal(2, obsv.last_msg[0].size)
|
|
132
|
+
assert_equal(:stop_method, obsv.last_msg[1][0])
|
|
133
|
+
assert_equal(2, obsv.last_msg[0].size)
|
|
134
|
+
assert_equal('hello', fm.hello)
|
|
135
|
+
assert_equal(2, fm.nb_method)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def test_accessor
|
|
139
|
+
assert_respond_to(ObjectMonitor.new(nil), :list_observers)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end # class ObjectMonitorTest
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
|
|
2
|
+
# Author: Nicolas Despres <polrop@lrde.epita.fr>.
|
|
3
|
+
# License: Gnu General Public License.
|
|
4
|
+
|
|
5
|
+
# $LastChangedBy: polrop $
|
|
6
|
+
# $Id: object_monitor_activity.rb 105 2005-01-16 17:42:26Z polrop $
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
require 'observable'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ObjectMonitorActivity
|
|
13
|
+
include Observable
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@mutex = Mutex.new
|
|
17
|
+
@activity = {}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def update(msg, info)
|
|
21
|
+
case msg
|
|
22
|
+
when :start_method: @mutex.synchronize { @activity[info[:num]] = info }
|
|
23
|
+
when :stop_method: @mutex.synchronize { @activity.delete(info[:num]) }
|
|
24
|
+
else raise 'unknown message'
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def snapshot
|
|
29
|
+
@mutex.synchronize { @activity.dup }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end # class ObjectMonitorActivity
|
|
33
|
+
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
|
|
2
|
+
# Author: Nicolas Despres <polrop@lrde.epita.fr>.
|
|
3
|
+
# License: Gnu General Public License.
|
|
4
|
+
|
|
5
|
+
# $LastChangedBy: polrop $
|
|
6
|
+
# $Id: observable.rb 98 2005-01-13 18:48:15Z polrop $
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
require 'observer'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
module Observable
|
|
13
|
+
|
|
14
|
+
def add_observers(*observers)
|
|
15
|
+
observers.each { |observer| add_observer(observer) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def observer?(observer)
|
|
19
|
+
if defined? @observer_peers
|
|
20
|
+
@observer_peers.include?(observer)
|
|
21
|
+
else
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def list_observers
|
|
27
|
+
if defined? @observer_peers
|
|
28
|
+
@observer_peers.dup
|
|
29
|
+
else
|
|
30
|
+
[]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def notify_observer(observer, *arg, &block)
|
|
35
|
+
if defined? @observer_state and @observer_state
|
|
36
|
+
if defined? @observer_peers
|
|
37
|
+
if @observer_peers.include?(observer)
|
|
38
|
+
observer.update(*arg, &block)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
@observer_state = false
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.included(klass)
|
|
46
|
+
klass.module_eval do
|
|
47
|
+
class << self
|
|
48
|
+
unless method_defined?(:notifier_methods_visibility)
|
|
49
|
+
def notifier_methods_visibility(visibility)
|
|
50
|
+
send(visibility, *instance_methods)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end # module Observable
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
if defined? TEST_MODE or __FILE__ == $0
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
require 'test/unit/ui/yaml/testrunner'
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ObservableTest < Test::Unit::TestCase
|
|
67
|
+
|
|
68
|
+
class Notify
|
|
69
|
+
include Observable
|
|
70
|
+
|
|
71
|
+
def initialize(*obsv)
|
|
72
|
+
obsv.each { |o| add_observer(o) }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end # class Notify
|
|
76
|
+
|
|
77
|
+
class Obsv
|
|
78
|
+
|
|
79
|
+
attr_reader :last_msg
|
|
80
|
+
|
|
81
|
+
def initialize
|
|
82
|
+
@last_msg = nil
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def update(arg)
|
|
86
|
+
@last_msg = arg
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
end # class Obsv
|
|
90
|
+
|
|
91
|
+
#
|
|
92
|
+
# Tests
|
|
93
|
+
#
|
|
94
|
+
def test_simple
|
|
95
|
+
o1 = Obsv.new
|
|
96
|
+
o2 = Obsv.new
|
|
97
|
+
n = Notify.new(o1, o2)
|
|
98
|
+
assert_equal(2, n.count_observers, 'bad number of observers')
|
|
99
|
+
assert(n.observer?(o1))
|
|
100
|
+
n.changed
|
|
101
|
+
n.notify_observers('all')
|
|
102
|
+
assert_equal('all', o1.last_msg, 'bad msg o1 1')
|
|
103
|
+
assert_equal('all', o2.last_msg, 'bad msg o2 1')
|
|
104
|
+
l = n.list_observers
|
|
105
|
+
assert_equal(o1, l[0], 'o1 is not at the right place in the list')
|
|
106
|
+
assert_equal(o2, l[1], 'o2 is not at the right place in the list')
|
|
107
|
+
n.changed
|
|
108
|
+
n.notify_observer(o1, 'o1')
|
|
109
|
+
assert_equal('o1', o1.last_msg, 'bad msg o1 2')
|
|
110
|
+
assert_equal('all', o2.last_msg, 'bad msg o2 2')
|
|
111
|
+
n.changed
|
|
112
|
+
n.notify_observer(o2, 'o2')
|
|
113
|
+
assert_equal('o1', o1.last_msg, 'bad msg o1 3')
|
|
114
|
+
assert_equal('o2', o2.last_msg, 'bad msg o2 3')
|
|
115
|
+
n.changed
|
|
116
|
+
n.notify_observer(o1, 'new_all')
|
|
117
|
+
n.changed
|
|
118
|
+
n.notify_observer(o2, 'new_all')
|
|
119
|
+
assert_equal('new_all', o1.last_msg, 'bad msg o1 4')
|
|
120
|
+
assert_equal('new_all', o2.last_msg, 'bad msg o2 4')
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
class ObservableMethodsVisibilityFoo
|
|
124
|
+
include Observable
|
|
125
|
+
|
|
126
|
+
notifier_methods_visibility(:protected)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_notifier_methods_visibility
|
|
130
|
+
fm = ObservableMethodsVisibilityFoo.new
|
|
131
|
+
assert_raises(NoMethodError) { fm.add_observer(Object.new) }
|
|
132
|
+
assert_raises(NoMethodError) { fm.notify_observer(Object.new) }
|
|
133
|
+
assert_raises(NoMethodError) { fm.list_observer }
|
|
134
|
+
assert_raises(NoMethodError) { fm.changed? }
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end # class ObservableTest
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
end
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
|
|
2
|
+
# Author: Nicolas Despres <polrop@lrde.epita.fr>.
|
|
3
|
+
# License: Gnu General Public License.
|
|
4
|
+
|
|
5
|
+
# $LastChangedBy: ertai $
|
|
6
|
+
# $Id: observable_pool.rb 186 2005-04-03 00:07:45Z ertai $
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
require 'observable'
|
|
10
|
+
require 'thread'
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
module ObservablePool
|
|
14
|
+
|
|
15
|
+
class Observer
|
|
16
|
+
include Observable
|
|
17
|
+
|
|
18
|
+
attr_reader :observable
|
|
19
|
+
|
|
20
|
+
def initialize(observable, mutex)
|
|
21
|
+
@observable = observable
|
|
22
|
+
@observable.add_observer(self)
|
|
23
|
+
@mutex = mutex
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def update(*args, &block)
|
|
27
|
+
@mutex.synchronize do
|
|
28
|
+
changed
|
|
29
|
+
notify_observers(@observable, *args, &block)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def method_missing(meth, *args, &block)
|
|
34
|
+
@observable.send(meth, *args, &block)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end # class Observer
|
|
38
|
+
|
|
39
|
+
def add_observable(observable)
|
|
40
|
+
unless observable.is_a?(Observable)
|
|
41
|
+
raise(ArgumentError, "observable object must be Observale")
|
|
42
|
+
end
|
|
43
|
+
@observable_peer_mutex = Mutex.new unless defined? @observable_peer_mutex
|
|
44
|
+
@observable_peers = {} unless defined? @observable_peers
|
|
45
|
+
sync_observer = Observer.new(observable, @observable_peer_mutex)
|
|
46
|
+
@observable_peers[observable] = sync_observer
|
|
47
|
+
@global_observer_peers = [] unless defined? @global_observer_peers
|
|
48
|
+
@global_observer_peers.each do |observer|
|
|
49
|
+
sync_observer.add_observer(observer)
|
|
50
|
+
end
|
|
51
|
+
sync_observer
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def add_observables(*observables)
|
|
55
|
+
observables.each { |observable| add_observable(observable) }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def delete_observable(observable)
|
|
59
|
+
@observable_peers.delete(observable) if defined? @observable_peers
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def delete_observables
|
|
63
|
+
@observable_peers.clear if defined? @observable_peers
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def observable(observable)
|
|
67
|
+
@observable_peers[observable] if defined? @observable_peers
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def observable?(observable)
|
|
71
|
+
@observable_peers.has_key?(observable) if defined? @observable_peers
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def list_observables
|
|
75
|
+
if defined? @observable_peers
|
|
76
|
+
@observable_peers.keys
|
|
77
|
+
else
|
|
78
|
+
[]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def list_observables_observed(observer)
|
|
83
|
+
observables = []
|
|
84
|
+
if defined? @observable_peers
|
|
85
|
+
@observable_peers.each do |observable, obsv|
|
|
86
|
+
if obsv.list_observers.include?(observer)
|
|
87
|
+
observables << observable
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
observables
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def count_observables
|
|
95
|
+
if defined? @observable_peers
|
|
96
|
+
@observable_peers.size
|
|
97
|
+
else
|
|
98
|
+
0
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def each_observables(&block)
|
|
103
|
+
if defined? @observable_peers
|
|
104
|
+
@observable_peers.each do |observable, observer|
|
|
105
|
+
block[observable, observer]
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def list_all_observers
|
|
111
|
+
observers = []
|
|
112
|
+
if defined? @observable_peers
|
|
113
|
+
@observable_peers.each do |observable, observer|
|
|
114
|
+
observers += observer.list_observers
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
observers.uniq
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def count_all_observers
|
|
121
|
+
list_observers.size
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def add_global_observer(observer)
|
|
125
|
+
if defined? @observable_peers
|
|
126
|
+
@observable_peers.each do |observable, obsv|
|
|
127
|
+
obsv.add_observer(observer) unless observable.observer?(observer)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
@global_observer_peers = [] unless defined? @global_observer_peers
|
|
131
|
+
@global_observer_peers << observer
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def add_global_observers(*observers)
|
|
135
|
+
observers.each { |observer| add_global_observer(observer) }
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def delete_global_observer(observer)
|
|
139
|
+
if defined? @observable_peers
|
|
140
|
+
@observable_peers.each do |observable, obsv|
|
|
141
|
+
obsv.delete_observer(observer)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
@global_observer_peers.delete(observer) if defined? @global_observer_peers
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def delete_global_observers
|
|
148
|
+
if defined? @global_observer_peers
|
|
149
|
+
@global_observer_peers.dup.each do |global_observer|
|
|
150
|
+
delete_global_observer(global_observer)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def list_global_observers
|
|
156
|
+
if defined? @global_observer_peers
|
|
157
|
+
@global_observer_peers.dup
|
|
158
|
+
else
|
|
159
|
+
[]
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def count_global_observers
|
|
164
|
+
if defined? @global_observer_peers
|
|
165
|
+
@globale.observer_peers.size
|
|
166
|
+
else
|
|
167
|
+
0
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def global_observer?(observer)
|
|
172
|
+
if defined? @global_observer_peers
|
|
173
|
+
@global_observer_peers.include?(observer)
|
|
174
|
+
else
|
|
175
|
+
false
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
end # class ObservablePool
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
if defined? TEST_MODE or __FILE__ == $0
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
require 'test/unit/ui/yaml/testrunner'
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class ObservablePoolTest < Test::Unit::TestCase
|
|
189
|
+
|
|
190
|
+
class Notifier
|
|
191
|
+
include Observable
|
|
192
|
+
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
class NotifierPool
|
|
196
|
+
include ObservablePool
|
|
197
|
+
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
class Obsv
|
|
201
|
+
|
|
202
|
+
attr_reader :last_msg
|
|
203
|
+
|
|
204
|
+
def initialize
|
|
205
|
+
@last_msg = nil
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def update(*args, &block)
|
|
209
|
+
@last_msg = args
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def test_simple
|
|
215
|
+
n1 = Notifier.new
|
|
216
|
+
n2 = Notifier.new
|
|
217
|
+
o1 = Obsv.new
|
|
218
|
+
o2 = Obsv.new
|
|
219
|
+
o3 = Obsv.new
|
|
220
|
+
op = NotifierPool.new
|
|
221
|
+
assert_equal(0, op.count_observables)
|
|
222
|
+
assert_equal([], op.list_observables)
|
|
223
|
+
op.add_observables(n1)
|
|
224
|
+
op.add_observable(n2)
|
|
225
|
+
op.observable(n2).add_observers(o1, o3)
|
|
226
|
+
assert_equal(2, op.count_observables)
|
|
227
|
+
[ n1, n2 ].each { |x| assert(op.list_observables.include?(x)) }
|
|
228
|
+
assert_equal(1, n1.count_observers)
|
|
229
|
+
assert_equal([], n1.list_observers[0].list_observers)
|
|
230
|
+
assert_equal(1, n2.count_observers)
|
|
231
|
+
assert_equal(2, n2.list_observers[0].count_observers)
|
|
232
|
+
[o1, o3].each do |x|
|
|
233
|
+
assert(n2.list_observers[0].list_observers.include?(x),
|
|
234
|
+
"#{x} not observer")
|
|
235
|
+
end
|
|
236
|
+
op.observable(n1).add_observers(o2, o3)
|
|
237
|
+
assert_equal(2, op.observable(n1).count_observers)
|
|
238
|
+
[o1, o2, o3].each do |x|
|
|
239
|
+
assert(op.list_all_observers.include?(x), "#{x} not observer")
|
|
240
|
+
end
|
|
241
|
+
n2.changed
|
|
242
|
+
n2.notify_observers('msg2')
|
|
243
|
+
assert_equal([ n2, 'msg2'], o1.last_msg)
|
|
244
|
+
assert_nil(o2.last_msg)
|
|
245
|
+
assert_equal([ n2, 'msg2'], o3.last_msg)
|
|
246
|
+
n1.changed
|
|
247
|
+
n1.notify_observers('msg1')
|
|
248
|
+
assert_equal([n2, 'msg2'], o1.last_msg)
|
|
249
|
+
assert_equal([n1, 'msg1'], o2.last_msg)
|
|
250
|
+
assert_equal([n1, 'msg1'], o3.last_msg)
|
|
251
|
+
[n1, n2].each do |x|
|
|
252
|
+
assert(op.list_observables_observed(o3).include?(x), "#{x} not observer")
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def test_global_observer
|
|
257
|
+
n1 = Notifier.new
|
|
258
|
+
n2 = Notifier.new
|
|
259
|
+
n3 = Notifier.new
|
|
260
|
+
o1 = Obsv.new
|
|
261
|
+
o2 = Obsv.new
|
|
262
|
+
o3 = Obsv.new
|
|
263
|
+
op = NotifierPool.new
|
|
264
|
+
assert_equal(0, op.count_global_observers)
|
|
265
|
+
assert_equal([], op.list_global_observers)
|
|
266
|
+
op.add_observables(n1)
|
|
267
|
+
op.add_observable(n2)
|
|
268
|
+
op.observable(n1).add_observers(o1)
|
|
269
|
+
op.observable(n2).add_observers(o2)
|
|
270
|
+
op.add_global_observers(o3)
|
|
271
|
+
[o1, o3].each do |x|
|
|
272
|
+
assert(n1.list_observers[0].list_observers.include?(x),
|
|
273
|
+
"#{x} not observer")
|
|
274
|
+
end
|
|
275
|
+
[o2, o3].each do |x|
|
|
276
|
+
assert(n2.list_observers[0].list_observers.include?(x),
|
|
277
|
+
"#{x} not observer")
|
|
278
|
+
end
|
|
279
|
+
assert_equal([o3], op.list_global_observers)
|
|
280
|
+
op.add_observable(n3)
|
|
281
|
+
assert([o3], n3.list_observers[0].list_observers)
|
|
282
|
+
op.delete_global_observers
|
|
283
|
+
assert_equal([], op.list_global_observers)
|
|
284
|
+
assert([], n3.list_observers[0].list_observers)
|
|
285
|
+
assert([o2], n2.list_observers[0].list_observers)
|
|
286
|
+
assert([o1], n1.list_observers[0].list_observers)
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
end # class ObservablePoolTest
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
end
|
|
293
|
+
|