auser-poolparty 0.2.66 → 0.2.67
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/Manifest.txt +83 -41
- data/PostInstall.txt +2 -2
- data/README.txt +1 -2
- data/Rakefile +14 -1
- data/bin/cloud-start +11 -10
- data/bin/{pool-spec → pool-generate} +0 -0
- data/bin/pool-init +3 -3
- data/bin/pool-start +8 -7
- data/bin/server-update-hosts +1 -1
- data/lib/erlang/messenger/ebin/pm_client_rel-0.1.rel +1 -1
- data/lib/erlang/messenger/ebin/pm_master_rel-0.1.rel +1 -1
- data/lib/erlang/messenger/ebin/pm_node_rel-0.1.rel +1 -1
- data/lib/erlang/messenger/include/defines.hrl +7 -3
- data/lib/erlang/messenger/lib/eunit/.svn/all-wcprops +53 -0
- data/lib/erlang/messenger/lib/eunit/.svn/entries +140 -0
- data/lib/erlang/messenger/lib/eunit/.svn/format +1 -0
- data/lib/erlang/messenger/lib/eunit/.svn/prop-base/NOTES.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/.svn/text-base/AUTHORS.svn-base +2 -0
- data/lib/erlang/messenger/lib/eunit/.svn/text-base/CHANGELOG.svn-base +14 -0
- data/lib/erlang/messenger/lib/eunit/.svn/text-base/COPYING.svn-base +504 -0
- data/lib/erlang/messenger/lib/eunit/.svn/text-base/NOTES.svn-base +276 -0
- data/lib/erlang/messenger/lib/eunit/.svn/text-base/README.svn-base +3 -0
- data/lib/erlang/messenger/lib/eunit/.svn/text-base/sys.config.svn-base +9 -0
- data/lib/erlang/messenger/lib/eunit/.svn/text-base/vsn.mk.svn-base +1 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/all-wcprops +59 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/entries +142 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/format +1 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/erlang.png.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/eunit.html.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/index.html.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/modules-frame.html.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/overview-summary.html.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/packages-frame.html.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/edoc-info.svn-base +3 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/erlang.png.svn-base +0 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/eunit.html.svn-base +172 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/index.html.svn-base +17 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/modules-frame.html.svn-base +12 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/overview-summary.html.svn-base +984 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/overview.edoc.svn-base +980 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/packages-frame.html.svn-base +11 -0
- data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/stylesheet.css.svn-base +55 -0
- data/lib/erlang/messenger/lib/eunit/ebin/.svn/all-wcprops +5 -0
- data/lib/erlang/messenger/lib/eunit/ebin/.svn/dir-prop-base +8 -0
- data/lib/erlang/messenger/lib/eunit/ebin/.svn/entries +28 -0
- data/lib/erlang/messenger/lib/eunit/ebin/.svn/format +1 -0
- data/lib/erlang/messenger/lib/eunit/examples/.svn/all-wcprops +23 -0
- data/lib/erlang/messenger/lib/eunit/examples/.svn/entries +66 -0
- data/lib/erlang/messenger/lib/eunit/examples/.svn/format +1 -0
- data/lib/erlang/messenger/lib/eunit/examples/.svn/prop-base/eunit_examples.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/examples/.svn/prop-base/fib.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/examples/.svn/text-base/eunit_examples.erl.svn-base +339 -0
- data/lib/erlang/messenger/lib/eunit/examples/.svn/text-base/fib.erl.svn-base +19 -0
- data/lib/erlang/messenger/lib/eunit/examples/.svn/text-base/tests.txt.svn-base +1 -0
- data/lib/erlang/messenger/lib/eunit/include/.svn/all-wcprops +11 -0
- data/lib/erlang/messenger/lib/eunit/include/.svn/entries +41 -0
- data/lib/erlang/messenger/lib/eunit/include/.svn/format +1 -0
- data/lib/erlang/messenger/lib/eunit/include/.svn/prop-base/eunit.hrl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/include/.svn/text-base/eunit.hrl.svn-base +313 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/all-wcprops +113 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/entries +259 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/format +1 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/autoload.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/code_monitor.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_autoexport.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_data.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_internal.hrl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_lib.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_proc.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_serial.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_server.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_striptests.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_test.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_tests.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_tty.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/file_monitor.erl.svn-base +5 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/autoload.erl.svn-base +388 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/code_monitor.erl.svn-base +243 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit.app.src.svn-base +21 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit.appup.src.svn-base +1 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit.erl.svn-base +196 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_autoexport.erl.svn-base +102 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_data.erl.svn-base +798 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_internal.hrl.svn-base +48 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_lib.erl.svn-base +682 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_proc.erl.svn-base +552 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_serial.erl.svn-base +157 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_server.erl.svn-base +340 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_striptests.erl.svn-base +64 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_test.erl.svn-base +334 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_tests.erl.svn-base +45 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_tty.erl.svn-base +272 -0
- data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/file_monitor.erl.svn-base +409 -0
- data/lib/erlang/messenger/pm_client_rel-0.1.boot +0 -0
- data/lib/erlang/messenger/pm_client_rel-0.1.script +77 -85
- data/lib/erlang/messenger/pm_master_rel-0.1.boot +0 -0
- data/lib/erlang/messenger/pm_master_rel-0.1.script +78 -85
- data/lib/erlang/messenger/pm_node_rel-0.1.boot +0 -0
- data/lib/erlang/messenger/pm_node_rel-0.1.script +77 -86
- data/lib/erlang/messenger/src/pm_node.erl +46 -9
- data/lib/erlang/messenger/src/utils.erl +7 -1
- data/lib/poolparty.rb +17 -23
- data/lib/poolparty/base_packages/poolparty.rb +1 -1
- data/lib/poolparty/core/string.rb +11 -2
- data/lib/poolparty/helpers/binary.rb +31 -0
- data/lib/poolparty/helpers/console.rb +25 -16
- data/lib/poolparty/helpers/nice_printer.rb +36 -0
- data/lib/poolparty/helpers/optioner.rb +8 -0
- data/lib/poolparty/helpers/provisioner_base.rb +7 -5
- data/lib/poolparty/helpers/provisioners/master.rb +1 -1
- data/lib/poolparty/helpers/provisioners/slave.rb +2 -1
- data/lib/poolparty/modules/cloud_resourcer.rb +1 -1
- data/lib/poolparty/modules/file_writer.rb +12 -1
- data/lib/poolparty/modules/resourcing_dsl.rb +2 -1
- data/lib/poolparty/monitors/base_monitor.rb +3 -0
- data/lib/poolparty/net/remoter.rb +13 -11
- data/lib/poolparty/pool/base.rb +25 -13
- data/lib/poolparty/pool/cloud.rb +32 -10
- data/lib/poolparty/pool/custom_resource.rb +16 -7
- data/lib/poolparty/pool/plugin_model.rb +2 -2
- data/lib/poolparty/pool/pool.rb +2 -2
- data/lib/poolparty/pool/resource.rb +25 -7
- data/lib/poolparty/pool/resources/class_package.rb +3 -2
- data/lib/poolparty/pool/resources/exec.rb +1 -1
- data/lib/poolparty/pool/resources/variable.rb +4 -0
- data/lib/poolparty/version.rb +1 -1
- data/poolparty.gemspec +13 -11
- data/spec/poolparty/core/hash_spec.rb +1 -1
- data/spec/poolparty/core/time_spec.rb +1 -1
- data/spec/poolparty/net/remote_spec.rb +1 -1
- data/spec/poolparty/pool/base_spec.rb +25 -20
- data/spec/poolparty/pool/cloud_spec.rb +50 -3
- data/spec/poolparty/pool/plugin_spec.rb +1 -0
- data/spec/poolparty/pool/resource_spec.rb +4 -3
- data/spec/poolparty/spec_helper.rb +3 -4
- data/tasks/deployment.rake +15 -3
- data/website/index.html +2 -2
- metadata +88 -46
- data/lib/erlang/messenger/Makefile +0 -15
- data/lib/erlang/messenger/lib/eunit/Makefile +0 -28
- data/lib/erlang/messenger/lib/eunit/ebin/autoload.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/code_monitor.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/eunit.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/eunit_autoexport.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/eunit_data.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/eunit_lib.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/eunit_proc.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/eunit_serial.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/eunit_server.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/eunit_striptests.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/eunit_test.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/eunit_tests.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/eunit_tty.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/ebin/file_monitor.beam +0 -0
- data/lib/erlang/messenger/lib/eunit/src/Makefile +0 -46
- data/lib/poolparty/config/allowed_commands.yml +0 -1
- data/lib/poolparty/plugins/git.rb +0 -45
- data/spec/poolparty/plugins/git_spec.rb +0 -40
@@ -0,0 +1,259 @@
|
|
1
|
+
8
|
2
|
+
|
3
|
+
dir
|
4
|
+
263
|
5
|
+
http://svn.process-one.net/contribs/trunk/eunit/src
|
6
|
+
http://svn.process-one.net/contribs
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
2008-10-02T07:09:39.920718Z
|
11
|
+
258
|
12
|
+
rcarlsson
|
13
|
+
|
14
|
+
|
15
|
+
svn:special svn:externals svn:needs-lock
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
5c723cce-c907-0410-9aa2-ab8348fff7a4
|
28
|
+
|
29
|
+
eunit_tests.erl
|
30
|
+
file
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
2008-10-18T23:25:36.000000Z
|
36
|
+
7bf5a76dd440923990c7b484df953d88
|
37
|
+
2007-11-15T10:23:54.688786Z
|
38
|
+
238
|
39
|
+
mremond
|
40
|
+
has-props
|
41
|
+
|
42
|
+
eunit_proc.erl
|
43
|
+
file
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
2008-10-18T23:25:36.000000Z
|
49
|
+
03043c0e066a109082097aef890fc37c
|
50
|
+
2008-09-29T17:42:21.837614Z
|
51
|
+
256
|
52
|
+
rcarlsson
|
53
|
+
has-props
|
54
|
+
|
55
|
+
autoload.erl
|
56
|
+
file
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
2008-10-18T23:25:36.000000Z
|
62
|
+
5e5050f0ad965ea25cb9ad302da9a217
|
63
|
+
2007-11-15T10:23:54.688786Z
|
64
|
+
238
|
65
|
+
mremond
|
66
|
+
has-props
|
67
|
+
|
68
|
+
eunit.app.src
|
69
|
+
file
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
2008-10-18T23:25:36.000000Z
|
75
|
+
3cf609893ad581006db46c7faccc018e
|
76
|
+
2007-05-05T14:47:04.988837Z
|
77
|
+
211
|
78
|
+
rcarlsson
|
79
|
+
|
80
|
+
eunit_server.erl
|
81
|
+
file
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
2008-10-18T23:25:36.000000Z
|
87
|
+
dbc03f7a823600ddee4be9a1b9390a44
|
88
|
+
2007-11-15T10:23:54.688786Z
|
89
|
+
238
|
90
|
+
mremond
|
91
|
+
has-props
|
92
|
+
|
93
|
+
eunit_lib.erl
|
94
|
+
file
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
2008-10-18T23:25:36.000000Z
|
100
|
+
e56a109d2b0ca2a4f0fea79b171345c0
|
101
|
+
2007-11-15T10:23:54.688786Z
|
102
|
+
238
|
103
|
+
mremond
|
104
|
+
has-props
|
105
|
+
|
106
|
+
eunit_data.erl
|
107
|
+
file
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
2008-10-18T23:25:36.000000Z
|
113
|
+
9991ae2d9a13cc8daa2afa605687459f
|
114
|
+
2008-09-29T17:13:43.707110Z
|
115
|
+
253
|
116
|
+
rcarlsson
|
117
|
+
has-props
|
118
|
+
|
119
|
+
eunit.appup.src
|
120
|
+
file
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
2008-10-18T23:25:36.000000Z
|
126
|
+
cb8fccb1c3eb4716a1497a2acaca200b
|
127
|
+
2007-05-05T14:47:04.988837Z
|
128
|
+
211
|
129
|
+
rcarlsson
|
130
|
+
|
131
|
+
eunit_autoexport.erl
|
132
|
+
file
|
133
|
+
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
2008-10-18T23:25:36.000000Z
|
138
|
+
5d1044347abc3dea56ca96165172ef6e
|
139
|
+
2008-10-02T07:09:39.920718Z
|
140
|
+
258
|
141
|
+
rcarlsson
|
142
|
+
has-props
|
143
|
+
|
144
|
+
code_monitor.erl
|
145
|
+
file
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
|
150
|
+
2008-10-18T23:25:36.000000Z
|
151
|
+
f572097b0ec7cafd2089f56a5eb7f9fe
|
152
|
+
2007-11-15T10:23:54.688786Z
|
153
|
+
238
|
154
|
+
mremond
|
155
|
+
has-props
|
156
|
+
|
157
|
+
eunit_serial.erl
|
158
|
+
file
|
159
|
+
|
160
|
+
|
161
|
+
|
162
|
+
|
163
|
+
2008-10-18T23:25:36.000000Z
|
164
|
+
cbef3435db2217b039b3a2c5ac1a9b4f
|
165
|
+
2008-05-11T20:06:45.605499Z
|
166
|
+
249
|
167
|
+
rcarlsson
|
168
|
+
has-props
|
169
|
+
|
170
|
+
eunit_internal.hrl
|
171
|
+
file
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
|
176
|
+
2008-10-18T23:25:36.000000Z
|
177
|
+
5004ef0c3c46afc59168be7f84f4d72e
|
178
|
+
2007-11-15T10:23:54.688786Z
|
179
|
+
238
|
180
|
+
mremond
|
181
|
+
has-props
|
182
|
+
|
183
|
+
eunit_test.erl
|
184
|
+
file
|
185
|
+
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
2008-10-18T23:25:36.000000Z
|
190
|
+
5002627123543a66a63ae39c2a9b8241
|
191
|
+
2007-11-15T10:23:54.688786Z
|
192
|
+
238
|
193
|
+
mremond
|
194
|
+
has-props
|
195
|
+
|
196
|
+
eunit.erl
|
197
|
+
file
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
2008-10-18T23:25:36.000000Z
|
203
|
+
6f5f15caa627e0ae275ccadcfc028acc
|
204
|
+
2008-05-11T20:06:45.605499Z
|
205
|
+
249
|
206
|
+
rcarlsson
|
207
|
+
has-props
|
208
|
+
|
209
|
+
eunit_tty.erl
|
210
|
+
file
|
211
|
+
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
2008-10-18T23:25:36.000000Z
|
216
|
+
81a970f0ac5baf4bb85175b7e135f1aa
|
217
|
+
2007-11-15T10:23:54.688786Z
|
218
|
+
238
|
219
|
+
mremond
|
220
|
+
has-props
|
221
|
+
|
222
|
+
file_monitor.erl
|
223
|
+
file
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
|
228
|
+
2008-10-18T23:25:36.000000Z
|
229
|
+
f2f7a2d45511f1990ed14e243bfaf563
|
230
|
+
2008-08-23T09:12:02.363609Z
|
231
|
+
250
|
232
|
+
rcarlsson
|
233
|
+
has-props
|
234
|
+
|
235
|
+
eunit_striptests.erl
|
236
|
+
file
|
237
|
+
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
2008-10-18T23:25:36.000000Z
|
242
|
+
1c4d2c7395132297628b6774ab39d327
|
243
|
+
2007-11-15T10:23:54.688786Z
|
244
|
+
238
|
245
|
+
mremond
|
246
|
+
has-props
|
247
|
+
|
248
|
+
Makefile
|
249
|
+
file
|
250
|
+
|
251
|
+
|
252
|
+
|
253
|
+
|
254
|
+
2008-10-18T23:25:36.000000Z
|
255
|
+
eb300b5f8d4ca4ce302536227aaf97fb
|
256
|
+
2008-01-31T21:22:36.813745Z
|
257
|
+
245
|
258
|
+
rcarlsson
|
259
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
8
|
@@ -0,0 +1,388 @@
|
|
1
|
+
%% This library is free software; you can redistribute it and/or modify
|
2
|
+
%% it under the terms of the GNU Lesser General Public License as
|
3
|
+
%% published by the Free Software Foundation; either version 2 of the
|
4
|
+
%% License, or (at your option) any later version.
|
5
|
+
%%
|
6
|
+
%% This library is distributed in the hope that it will be useful, but
|
7
|
+
%% WITHOUT ANY WARRANTY; without even the implied warranty of
|
8
|
+
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
9
|
+
%% Lesser General Public License for more details.
|
10
|
+
%%
|
11
|
+
%% You should have received a copy of the GNU Lesser General Public
|
12
|
+
%% License along with this library; if not, write to the Free Software
|
13
|
+
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
14
|
+
%% USA
|
15
|
+
%%
|
16
|
+
%% $Id:$
|
17
|
+
%%
|
18
|
+
%% @private (for now)
|
19
|
+
%% @author Richard Carlsson <richardc@it.uu.se>
|
20
|
+
%% @copyright 2006 Richard Carlsson
|
21
|
+
%% @doc Erlang automatic code loading service
|
22
|
+
|
23
|
+
-module(autoload).
|
24
|
+
|
25
|
+
-export([start/0, start/1, stop/0, stop/1,
|
26
|
+
watch_module/1, watch_module/2, watch_module/3,
|
27
|
+
watch_file/1, watch_file/2, watch_file/3,
|
28
|
+
watch_dir/1, watch_dir/2, watch_dir/3
|
29
|
+
]).
|
30
|
+
|
31
|
+
-include_lib("kernel/include/file.hrl").
|
32
|
+
|
33
|
+
-define(SERVER, autoload).
|
34
|
+
-define(ZERO_TIMESTAMP, {0,0,0}).
|
35
|
+
|
36
|
+
%% TODO: un-watching functionality
|
37
|
+
|
38
|
+
%% We're not trying to provide strong guarantees here. The autoloader is
|
39
|
+
%% supposed to behave like a human assistant might - race conditions may
|
40
|
+
%% cause modules to be reloaded twice, or cause a reload from the wrong
|
41
|
+
%% file (if paths are suddenly changed).
|
42
|
+
|
43
|
+
|
44
|
+
watch_dir(Path) ->
|
45
|
+
watch_dir(Path, []).
|
46
|
+
|
47
|
+
watch_dir(Path, Opts) ->
|
48
|
+
watch_dir(?SERVER, Path, Opts).
|
49
|
+
|
50
|
+
watch_dir(Server, Path, Opts) ->
|
51
|
+
command(Server, {watch, {dir, filename:flatten(Path)}, Opts}).
|
52
|
+
|
53
|
+
watch_file(Path) ->
|
54
|
+
watch_file(Path, []).
|
55
|
+
|
56
|
+
watch_file(Path, Opts) ->
|
57
|
+
watch_file(?SERVER, Path, Opts).
|
58
|
+
|
59
|
+
watch_file(Server, Path, Opts) ->
|
60
|
+
command(Server, {watch, {file, filename:flatten(Path)}, Opts}).
|
61
|
+
|
62
|
+
watch_module(Module) ->
|
63
|
+
watch_module(Module, []).
|
64
|
+
|
65
|
+
watch_module(Module, Opts) ->
|
66
|
+
watch_module(?SERVER, Module, Opts).
|
67
|
+
|
68
|
+
watch_module(Server, Module, Opts) when is_atom(Module) ->
|
69
|
+
command(Server, {watch, {module, Module}, Opts}).
|
70
|
+
|
71
|
+
|
72
|
+
command(Server, Msg) ->
|
73
|
+
ServerPid = ensure_started(Server),
|
74
|
+
ServerPid ! {command, self(), Msg},
|
75
|
+
receive
|
76
|
+
{ServerPid, Result} -> Result
|
77
|
+
end.
|
78
|
+
|
79
|
+
stop() ->
|
80
|
+
stop(?SERVER).
|
81
|
+
|
82
|
+
stop(Server) ->
|
83
|
+
Server ! stop,
|
84
|
+
ok.
|
85
|
+
|
86
|
+
ensure_started(Name) when is_atom(Name) ->
|
87
|
+
start(Name);
|
88
|
+
ensure_started(Pid) when is_pid(Pid) ->
|
89
|
+
Pid.
|
90
|
+
|
91
|
+
|
92
|
+
start() ->
|
93
|
+
start(?SERVER).
|
94
|
+
|
95
|
+
start(Name) ->
|
96
|
+
case whereis(Name) of
|
97
|
+
undefined ->
|
98
|
+
Parent = self(),
|
99
|
+
Pid = spawn(fun () -> server_init(Name, Parent) end),
|
100
|
+
receive
|
101
|
+
{Pid, ok} -> Pid;
|
102
|
+
{Pid, error} -> throw(no_server)
|
103
|
+
end;
|
104
|
+
Pid -> Pid
|
105
|
+
end.
|
106
|
+
|
107
|
+
-record(state, {name, modules, files, dirs}).
|
108
|
+
|
109
|
+
-record(module, {time = ?ZERO_TIMESTAMP, file, opts = []}).
|
110
|
+
|
111
|
+
server_init(Name, Parent) ->
|
112
|
+
Self = self(),
|
113
|
+
case catch register(Name, Self) of
|
114
|
+
true ->
|
115
|
+
Parent ! {Self, ok},
|
116
|
+
code_monitor:monitor(self()),
|
117
|
+
server(#state{name = Name,
|
118
|
+
modules = dict:new(),
|
119
|
+
files = dict:new(),
|
120
|
+
dirs = dict:new()});
|
121
|
+
_ ->
|
122
|
+
init_failure(Parent)
|
123
|
+
end.
|
124
|
+
|
125
|
+
init_failure(Parent) ->
|
126
|
+
Parent ! {self(), error},
|
127
|
+
exit(failed).
|
128
|
+
|
129
|
+
server(St) ->
|
130
|
+
receive
|
131
|
+
{file_monitor, _Ref, Msg} ->
|
132
|
+
file_event(Msg, St);
|
133
|
+
{code_monitor, Msg} ->
|
134
|
+
code_event(Msg, St);
|
135
|
+
{command, From, Cmd} ->
|
136
|
+
server_command(From, Cmd, St);
|
137
|
+
stop ->
|
138
|
+
exit(normal);
|
139
|
+
Msg ->
|
140
|
+
erlang:display({autoload_unexpected, Msg}),
|
141
|
+
server(St)
|
142
|
+
end.
|
143
|
+
|
144
|
+
server_command_reply(From, Msg) ->
|
145
|
+
From ! {self(), Msg}.
|
146
|
+
|
147
|
+
server_command(From, {watch, {dir, Path}, Opts}, St) ->
|
148
|
+
server_command_reply(From, ok),
|
149
|
+
server(monitor_dir(Path, Opts, St));
|
150
|
+
server_command(From, {watch, {file, Path}, Opts}, St) ->
|
151
|
+
server_command_reply(From, ok),
|
152
|
+
server(monitor_file(Path, Opts, St));
|
153
|
+
server_command(From, {watch, {module, M}, Opts}, St) ->
|
154
|
+
server_command_reply(From, ok),
|
155
|
+
server(monitor_module(M, Opts, St)).
|
156
|
+
|
157
|
+
file_event({exists, Path, dir, _Info, Files}, St) ->
|
158
|
+
%%erlang:display({autoload_saw_exists, dir, Path}),
|
159
|
+
server(monitor_objs(Path, Files, St));
|
160
|
+
file_event({exists, Path, file, Info, _}, St) ->
|
161
|
+
%%erlang:display({autoload_saw_exists, file, Path}),
|
162
|
+
%% treat file-exists messages just like file-changed messages
|
163
|
+
server(changed_file(Path, Info#file_info.mtime, St));
|
164
|
+
file_event({changed, Path, dir, _Info, Files}, St) ->
|
165
|
+
%%erlang:display({autoload_saw_changed, dir, Path}),
|
166
|
+
server(monitor_objs(Path, Files, St));
|
167
|
+
file_event({changed, Path, file, #file_info{}=Info, _}, St) ->
|
168
|
+
%%erlang:display({autoload_saw_changed, file, Path}),
|
169
|
+
server(changed_file(Path, Info#file_info.mtime, St));
|
170
|
+
file_event({error, _Path, file, _ErrorAtom}=_Msg, St) ->
|
171
|
+
%%erlang:display({autoload_ignoring, _Msg}),
|
172
|
+
%% just consider the files as being temporarily unavailable
|
173
|
+
server(St);
|
174
|
+
file_event(_Msg, St) ->
|
175
|
+
erlang:display({autoload_unexpected_file_event, _Msg}),
|
176
|
+
server(St).
|
177
|
+
|
178
|
+
code_event({loaded, M, Time}, St) ->
|
179
|
+
%%erlang:display({autoload_saw_loaded, M, Time}),
|
180
|
+
server(loaded_module(M, Time, St));
|
181
|
+
code_event(_Msg, St) ->
|
182
|
+
erlang:display({autoload_unexpected_code_event, _Msg}),
|
183
|
+
server(St).
|
184
|
+
|
185
|
+
|
186
|
+
%% called when asked to watch a module M
|
187
|
+
|
188
|
+
monitor_module(M, Opts, St) ->
|
189
|
+
ensure_loaded(M, "", Opts),
|
190
|
+
case code:which(M) of
|
191
|
+
non_existing ->
|
192
|
+
%% no module loaded or found in path (e.g., the user has not
|
193
|
+
%% run 'make' yet, or has not updated the path): store
|
194
|
+
%% mapping from M to undefined file, for late binding
|
195
|
+
store_record(M, #module{opts = Opts}, St);
|
196
|
+
File when is_list(File) ->
|
197
|
+
%% existing file found (already loaded or in path): monitor
|
198
|
+
%% the file and map M to that file (even if the first load
|
199
|
+
%% might turn out to be from another file)
|
200
|
+
store_record(M, #module{file = File},
|
201
|
+
monitor_file(File, Opts, St));
|
202
|
+
_ ->
|
203
|
+
%% preloaded or cover-compiled module - ignore
|
204
|
+
St
|
205
|
+
end.
|
206
|
+
|
207
|
+
%% called when a monitored directory is detected as new or changed
|
208
|
+
|
209
|
+
monitor_objs(Path, Files, St) ->
|
210
|
+
Opts = get_dir_opts(Path, St),
|
211
|
+
ObjExt = file:objfile_extension(),
|
212
|
+
Objs = [F || {added, F} <- Files, filename:extension(F) == ObjExt],
|
213
|
+
lists:foldl(
|
214
|
+
fun (F, St) ->
|
215
|
+
F1 = filename:absname(filename:join(Path, F)),
|
216
|
+
%%erlang:display({autoload_monitoring, file, F1}),
|
217
|
+
monitor_file(F1, Opts, St)
|
218
|
+
end,
|
219
|
+
St,
|
220
|
+
Objs).
|
221
|
+
|
222
|
+
get_dir_opts(Path, St) ->
|
223
|
+
case dict:find(Path, St#state.dirs) of
|
224
|
+
{ok, {_Ref, Opts}} -> Opts;
|
225
|
+
error -> []
|
226
|
+
end.
|
227
|
+
|
228
|
+
%% called when a module was detected as loaded or reloaded (either
|
229
|
+
%% caused by an auto-load or by someone else)
|
230
|
+
|
231
|
+
loaded_module(M, Time, St) ->
|
232
|
+
case find_record(M, St) of
|
233
|
+
{ok, R} ->
|
234
|
+
File = code:which(M),
|
235
|
+
case R#module.file of
|
236
|
+
undefined when is_list(File) ->
|
237
|
+
%% a watched module gets a late binding to a file
|
238
|
+
%%erlang:display({autoload_late_binding, M, File}),
|
239
|
+
Opts = R#module.opts,
|
240
|
+
update_record(M, R, Time, File,
|
241
|
+
monitor_file(File, Opts, St));
|
242
|
+
File when is_list(File) ->
|
243
|
+
%% loaded from watched file - update the load time
|
244
|
+
update_record(M, R, Time, File, St);
|
245
|
+
_ ->
|
246
|
+
St %% not loaded from the watched file
|
247
|
+
end;
|
248
|
+
error ->
|
249
|
+
St %% uninteresting module
|
250
|
+
end.
|
251
|
+
|
252
|
+
|
253
|
+
%% called whenever a file has changed and exists
|
254
|
+
|
255
|
+
changed_file(File, Time, St) ->
|
256
|
+
%% always reread the module name from the file
|
257
|
+
case obj_module(File) of
|
258
|
+
{module, M} ->
|
259
|
+
case find_record(M, St) of
|
260
|
+
{ok, R} ->
|
261
|
+
check_reload(M, File, Time, R),
|
262
|
+
St;
|
263
|
+
error ->
|
264
|
+
%% first time we see this module: map to file
|
265
|
+
%% and don't try to reload
|
266
|
+
R = #module{file = File},
|
267
|
+
store_record(M, R, St)
|
268
|
+
end;
|
269
|
+
error ->
|
270
|
+
St %% bad file - ignore until changed again
|
271
|
+
end.
|
272
|
+
|
273
|
+
|
274
|
+
%% check if a module needs to be reloaded, when its file has changed
|
275
|
+
|
276
|
+
check_reload(M, File, Time, R) ->
|
277
|
+
%%erlang:display({autoload_checking, M, File, Time, R}),
|
278
|
+
case ((R#module.file == File)
|
279
|
+
andalso is_loaded(M)
|
280
|
+
andalso (code:which(M) == File)
|
281
|
+
andalso is_newer(Time, R#module.time))
|
282
|
+
of
|
283
|
+
true ->
|
284
|
+
reload(M);
|
285
|
+
false ->
|
286
|
+
ok
|
287
|
+
end.
|
288
|
+
|
289
|
+
|
290
|
+
reload(M) ->
|
291
|
+
erlang:display({autoload_loading, M}),
|
292
|
+
code:purge(M),
|
293
|
+
code:load_file(M).
|
294
|
+
|
295
|
+
update_record(M, R, Time, File, St) ->
|
296
|
+
store_record(M, R#module{time = Time, file = File}, St).
|
297
|
+
|
298
|
+
find_record(M, St) ->
|
299
|
+
dict:find(M, St#state.modules).
|
300
|
+
|
301
|
+
store_record(M, R, St) ->
|
302
|
+
St#state{modules = dict:store(M, R, St#state.modules)}.
|
303
|
+
|
304
|
+
%% we must remember watched files/dirs, so we don't set up more than one
|
305
|
+
%% file monitor for the same path, and so we can cancel monitors; for
|
306
|
+
%% dirs, we also remember options
|
307
|
+
|
308
|
+
monitor_file(Path, Opts, St) ->
|
309
|
+
ensure_loaded([], Path, Opts),
|
310
|
+
case dict:is_key(Path, St#state.files) of
|
311
|
+
true ->
|
312
|
+
%%erlang:display({autoload_already_watching, Path}),
|
313
|
+
St;
|
314
|
+
false ->
|
315
|
+
{ok, _, Ref} = file_monitor:monitor_file(Path, self()),
|
316
|
+
St#state{files = dict:store(Path, Ref, St#state.files)}
|
317
|
+
end.
|
318
|
+
|
319
|
+
monitor_dir(Path, Opts, St) ->
|
320
|
+
case dict:is_key(Path, St#state.dirs) of
|
321
|
+
true ->
|
322
|
+
%%erlang:display({autoload_already_watching, Path}),
|
323
|
+
St;
|
324
|
+
false ->
|
325
|
+
{ok, _, Ref} = file_monitor:monitor_dir(Path, self()),
|
326
|
+
St#state{dirs = dict:store(Path, {Ref, Opts},
|
327
|
+
St#state.dirs)}
|
328
|
+
end.
|
329
|
+
|
330
|
+
%% try to ensure that a module/file is loaded (M is [] if unknown;
|
331
|
+
%% File is "" if unknown)
|
332
|
+
|
333
|
+
ensure_loaded(M, File, Opts) ->
|
334
|
+
case proplists:get_bool(load, Opts) of
|
335
|
+
true when is_atom(M) ->
|
336
|
+
ensure_loaded_1(M, File); %% known module name
|
337
|
+
true when M == [] ->
|
338
|
+
case obj_module(File) of
|
339
|
+
{module, Module} ->
|
340
|
+
ensure_loaded_1(Module, File);
|
341
|
+
error ->
|
342
|
+
ok %% couldn't load
|
343
|
+
end;
|
344
|
+
false -> ok
|
345
|
+
end.
|
346
|
+
|
347
|
+
ensure_loaded_1(M, File) ->
|
348
|
+
%% always try to load using the path first
|
349
|
+
case code:ensure_loaded(M) of
|
350
|
+
{module, _} ->
|
351
|
+
ok;
|
352
|
+
{error, _} when File == [] ->
|
353
|
+
ok; %% ignore error
|
354
|
+
{error, _} ->
|
355
|
+
%% try loading directly from the file
|
356
|
+
code:load_abs(File) %% ignore result
|
357
|
+
end.
|
358
|
+
|
359
|
+
%% find name of module stored in an object file
|
360
|
+
|
361
|
+
obj_module(File) ->
|
362
|
+
case beam_lib:info(File) of
|
363
|
+
List when is_list(List) ->
|
364
|
+
case lists:keysearch(module, 1, List) of
|
365
|
+
{value, {module, M}} ->
|
366
|
+
{module, M};
|
367
|
+
_ ->
|
368
|
+
error
|
369
|
+
end;
|
370
|
+
_ ->
|
371
|
+
error
|
372
|
+
end.
|
373
|
+
|
374
|
+
%% check if the file timestamp (on DateTime format) is newer than
|
375
|
+
%% the module load-time (on Now-format)
|
376
|
+
|
377
|
+
is_newer(DateTime, LoadTime) ->
|
378
|
+
calendar:datetime_to_gregorian_seconds(DateTime) >
|
379
|
+
calendar:datetime_to_gregorian_seconds(
|
380
|
+
calendar:now_to_local_time(LoadTime)).
|
381
|
+
|
382
|
+
%% wrapper for code:is_loaded/1
|
383
|
+
|
384
|
+
is_loaded(Module) ->
|
385
|
+
case code:is_loaded(Module) of
|
386
|
+
{file, _} -> true;
|
387
|
+
false -> false
|
388
|
+
end.
|