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.
Files changed (132) hide show
  1. data/Rakefile +17 -3
  2. data/bin/vcs +57 -34
  3. data/doc/jamis.rb +564 -0
  4. data/ruby_ex/abstract.rb +254 -0
  5. data/ruby_ex/abstract_node.rb +85 -0
  6. data/ruby_ex/algorithms/simulated_annealing.rb +140 -0
  7. data/ruby_ex/array_each_pair.rb +18 -0
  8. data/ruby_ex/ask.rb +101 -0
  9. data/ruby_ex/attributed_class.rb +302 -0
  10. data/ruby_ex/cache.rb +373 -0
  11. data/ruby_ex/checkout.rb +12 -0
  12. data/ruby_ex/choose.rb +271 -0
  13. data/ruby_ex/commands.rb +18 -0
  14. data/ruby_ex/commands/command.rb +401 -0
  15. data/ruby_ex/commands/datas.rb +16 -0
  16. data/ruby_ex/commands/datas/data.rb +33 -0
  17. data/ruby_ex/commands/datas/factory.rb +66 -0
  18. data/ruby_ex/commands/factory.rb +66 -0
  19. data/ruby_ex/commands/helpers.rb +67 -0
  20. data/ruby_ex/commands/pipe.rb +64 -0
  21. data/ruby_ex/commands/runners.rb +17 -0
  22. data/ruby_ex/commands/runners/exec.rb +49 -0
  23. data/ruby_ex/commands/runners/fork.rb +97 -0
  24. data/ruby_ex/commands/runners/runner.rb +107 -0
  25. data/ruby_ex/commands/seq.rb +27 -0
  26. data/ruby_ex/config_file.rb +96 -0
  27. data/ruby_ex/const_regexp.rb +59 -0
  28. data/ruby_ex/daemon.rb +134 -0
  29. data/ruby_ex/diff.rb +667 -0
  30. data/ruby_ex/dlogger.rb +62 -0
  31. data/ruby_ex/drb/dispatcher.rb +252 -0
  32. data/ruby_ex/drb/dispatcher_server_test.rb +29 -0
  33. data/ruby_ex/drb/drb_observable.rb +97 -0
  34. data/ruby_ex/drb/drb_observable_pool.rb +27 -0
  35. data/ruby_ex/drb/drb_service.rb +43 -0
  36. data/ruby_ex/drb/drb_undumped_attributes.rb +55 -0
  37. data/ruby_ex/drb/drb_undumped_indexed_object.rb +54 -0
  38. data/ruby_ex/drb/insecure_protected_methods.rb +103 -0
  39. data/ruby_ex/drb/session_client_test.rb +40 -0
  40. data/ruby_ex/drb/session_manager.rb +246 -0
  41. data/ruby_ex/drb/session_server.rb +53 -0
  42. data/ruby_ex/dtime.rb +143 -0
  43. data/ruby_ex/dumpable_proc.rb +63 -0
  44. data/ruby_ex/exception.rb +32 -0
  45. data/ruby_ex/filetype.rb +229 -0
  46. data/ruby_ex/fileutils_ex.rb +44 -0
  47. data/ruby_ex/fold.rb +58 -0
  48. data/ruby_ex/generate_id.rb +44 -0
  49. data/ruby_ex/hookable.rb +262 -0
  50. data/ruby_ex/hooker.rb +54 -0
  51. data/ruby_ex/inactive_timeout.rb +137 -0
  52. data/ruby_ex/indexed_node.rb +66 -0
  53. data/ruby_ex/io_marshal.rb +100 -0
  54. data/ruby_ex/ioo.rb +194 -0
  55. data/ruby_ex/labeled_node.rb +63 -0
  56. data/ruby_ex/logger_observer.rb +23 -0
  57. data/ruby_ex/md5sum.rb +66 -0
  58. data/ruby_ex/mktemp.rb +208 -0
  59. data/ruby_ex/module/attr_once.rb +36 -0
  60. data/ruby_ex/module/autoload_tree.rb +75 -0
  61. data/ruby_ex/module/hierarchy.rb +335 -0
  62. data/ruby_ex/module/instance_method_visibility.rb +73 -0
  63. data/ruby_ex/module_ex.rb +11 -0
  64. data/ruby_ex/node.rb +80 -0
  65. data/ruby_ex/object_monitor.rb +145 -0
  66. data/ruby_ex/object_monitor_activity.rb +33 -0
  67. data/ruby_ex/observable.rb +140 -0
  68. data/ruby_ex/observable_pool.rb +293 -0
  69. data/ruby_ex/orderedhash.rb +252 -0
  70. data/ruby_ex/pathname_ex.rb +152 -0
  71. data/ruby_ex/pp_hierarchy.rb +29 -0
  72. data/ruby_ex/pseudo_cache.rb +190 -0
  73. data/ruby_ex/queue.rb +56 -0
  74. data/ruby_ex/random_generators.rb +25 -0
  75. data/ruby_ex/random_generators/random_generator.rb +31 -0
  76. data/ruby_ex/random_generators/ruby.rb +23 -0
  77. data/ruby_ex/safe_eval.rb +348 -0
  78. data/ruby_ex/sendmail.rb +215 -0
  79. data/ruby_ex/service_manager.rb +121 -0
  80. data/ruby_ex/session/administrable.rb +120 -0
  81. data/ruby_ex/session/client.rb +153 -0
  82. data/ruby_ex/session/const.rb +18 -0
  83. data/ruby_ex/session/dispatcher.rb +184 -0
  84. data/ruby_ex/session/error.rb +21 -0
  85. data/ruby_ex/session/fetchable.rb +57 -0
  86. data/ruby_ex/session/fetcher.rb +62 -0
  87. data/ruby_ex/session/hookable.rb +26 -0
  88. data/ruby_ex/session/profile.rb +110 -0
  89. data/ruby_ex/session/server.rb +582 -0
  90. data/ruby_ex/session/test/administrable_test.rb +337 -0
  91. data/ruby_ex/session/test/basic_test.rb +523 -0
  92. data/ruby_ex/session/test/dispatcher_test.rb +409 -0
  93. data/ruby_ex/session/test/fetchable_test.rb +119 -0
  94. data/ruby_ex/session/test/sub_server_test.rb +188 -0
  95. data/ruby_ex/shuffle.rb +30 -0
  96. data/ruby_ex/spring.rb +136 -0
  97. data/ruby_ex/spring_set.rb +137 -0
  98. data/ruby_ex/string_ex.rb +28 -0
  99. data/ruby_ex/symtbl.rb +106 -0
  100. data/ruby_ex/synflow.rb +474 -0
  101. data/ruby_ex/test/unit/ui/yaml/testrunner.rb +164 -0
  102. data/ruby_ex/thread_mutex.rb +10 -0
  103. data/ruby_ex/timeout_ex.rb +81 -0
  104. data/ruby_ex/top_down.rb +73 -0
  105. data/ruby_ex/trace.rb +26 -0
  106. data/ruby_ex/uri/druby.rb +81 -0
  107. data/ruby_ex/uri/file.rb +65 -0
  108. data/ruby_ex/uri/ftp_ex.rb +37 -0
  109. data/ruby_ex/uri/http_ex.rb +43 -0
  110. data/ruby_ex/uri/ssh.rb +92 -0
  111. data/ruby_ex/uri/svn.rb +118 -0
  112. data/ruby_ex/uri_ex.rb +45 -0
  113. data/ruby_ex/verbose_object.rb +30 -0
  114. data/ruby_ex/version.rb +66 -0
  115. data/ruby_ex/yaml/basenode_ext.rb +63 -0
  116. data/ruby_ex/yaml/chop_header.rb +23 -0
  117. data/ruby_ex/yaml/transform.rb +449 -0
  118. data/ruby_ex/yaml/yregexpath.rb +76 -0
  119. data/src/changelog.rb +28 -18
  120. data/src/conflict.rb +20 -0
  121. data/src/diff.rb +18 -0
  122. data/src/diffstat.rb +9 -3
  123. data/src/last_changed_date.rb +18 -0
  124. data/src/mail.rb +33 -65
  125. data/src/message.rb +15 -9
  126. data/src/mycommit.rb +29 -14
  127. data/src/news.rb +24 -3
  128. data/src/status.rb +17 -0
  129. data/src/svn.rb +2 -2
  130. data/src/vcs.rb +24 -3
  131. metadata +124 -5
  132. data/lrdetools.rb +0 -12
@@ -0,0 +1,12 @@
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: checkout.rb 159 2005-02-18 12:07:23Z polrop $
7
+
8
+ require 'uri_ex'
9
+ require 'uri/http_ex'
10
+ require 'uri/ftp_ex'
11
+ require 'uri/file'
12
+ require 'uri/svn'
@@ -0,0 +1,271 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: choose.rb 219 2005-05-09 12:26:29Z ertai $
5
+
6
+
7
+ require 'random_generators'
8
+
9
+
10
+ class Integer
11
+
12
+ def self.choose ( limit=nil, generator=nil )
13
+ limit.to_i.choose(generator)
14
+ end
15
+
16
+ def choose ( generator=nil )
17
+ (generator || RandomGenerators.default).choose_integer(self)
18
+ end
19
+
20
+ end # class Integer
21
+
22
+
23
+
24
+ class Float
25
+
26
+ def self.choose ( limit=nil, generator=nil )
27
+ (limit || 1.0).to_f.choose(generator)
28
+ end
29
+
30
+ def choose ( generator=nil )
31
+ (generator || RandomGenerators.default).choose_float(self)
32
+ end
33
+
34
+ end # class Float
35
+
36
+
37
+
38
+ class Hash
39
+
40
+ def choose ( limit=nil, generator=nil )
41
+ self[keys.choose(limit, generator)]
42
+ end
43
+
44
+ end # class Hash
45
+
46
+
47
+
48
+ class Array
49
+
50
+ def choose ( limit=nil, generator=nil )
51
+ n = size
52
+
53
+ # Out of limits: limit > size (FIXME warn)
54
+ limit = n if limit.nil? or limit > n
55
+
56
+ self[limit.choose(generator)]
57
+ end
58
+
59
+ end # class Array
60
+
61
+
62
+
63
+ module Enumerable
64
+
65
+ def choose ( limit=nil, generator=nil )
66
+ to_a.choose(limit, generator)
67
+ end
68
+
69
+ end # module Enumerable
70
+
71
+
72
+
73
+ class Range
74
+
75
+ def choose ( generator=nil )
76
+ case first
77
+ when Integer
78
+ first + (last + 1 - first).choose(generator)
79
+ else
80
+ super(nil, generator)
81
+ end
82
+ end
83
+
84
+ end # class Array
85
+
86
+
87
+
88
+ if $0 == __FILE__
89
+
90
+ class MockRandomGenerator < RandomGenerators::RandomGenerator
91
+ concrete
92
+ attr_reader :ref
93
+ def initialize ( tab_i, tab_f )
94
+ raise unless tab_i.is_a? Array
95
+ raise unless tab_f.is_a? Array
96
+ @ref, @ref_f, @pos = tab_i, tab_f, -1
97
+ end
98
+ def get ( tab )
99
+ tab[@pos = (@pos + 1) % tab.size]
100
+ end
101
+ def choose_integer ( n )
102
+ check_choose_integer(n)
103
+ get(@ref) % n
104
+ end
105
+ def choose_float ( f=1.0 )
106
+ check_choose_float(f)
107
+ get(@ref_f) * f
108
+ end
109
+ end # class MockRandomGenerator
110
+
111
+ class RandomMockRandomGenerator < MockRandomGenerator
112
+ def initialize ( n )
113
+ tab_i = (0 .. n - 1).to_a.shuffle
114
+ tab_f = []
115
+ n.times { tab_f << Float.choose() }
116
+ super(tab_i, tab_f)
117
+ end
118
+ end # class RandomMockRandomGenerator
119
+
120
+
121
+ require 'test/unit'
122
+ require 'set'
123
+
124
+ class ChooseTest < Test::Unit::TestCase
125
+
126
+ REF_5 = [1, 2, 4, 0, 3]
127
+ REF_F_5 = [0.187528345035389, 0.368857819121331, 0.06954449811019,
128
+ 0.188887464581057, 0.213757352204993]
129
+ REF_50 = [
130
+ 28, 12, 17, 10, 1, 37, 46, 25, 47, 2, 45, 36, 20, 5, 30, 14, 18, 39,
131
+ 8, 15, 16, 43, 27, 33, 22, 7, 32, 3, 35, 9, 19, 13, 21, 6, 23, 26, 4,
132
+ 40, 44, 11, 49, 29, 42, 24, 31, 48, 34, 0, 38, 41
133
+ ]
134
+ REF_F_50 = [
135
+ 0.643785412423313, 0.765736325876787, 0.604515956481919,
136
+ 0.133839202811942, 0.350400971015915, 0.966710213804618,
137
+ 0.904755113180727, 0.88459848286584, 0.163951952941716,
138
+ 0.808023529592901, 0.387806572020054, 0.659689131658524,
139
+ 0.289974238490686, 0.813535830006003, 0.565311754588038,
140
+ 0.889200099511072, 0.0668127918615937, 0.992091996129602,
141
+ 0.604403987759724, 0.89254002738744, 0.601499371463433,
142
+ 0.754795648856089, 0.751190354581922, 0.434389552799985,
143
+ 0.761369747575372, 0.174903159961104, 0.940325234550983,
144
+ 0.536097376374528, 0.957906004507095, 0.693120914744213,
145
+ 0.23448576242663, 0.638284107437357, 0.423910334473476,
146
+ 0.251349127152935, 0.457931924844161, 0.20579389645718,
147
+ 0.256057573715225, 0.584466924890876, 0.609375598141924,
148
+ 0.0856487881392241, 0.437958877766505, 0.432312048738822,
149
+ 0.81560374982655, 0.142059376928955, 0.118824432371184,
150
+ 0.958816710859537, 0.69899930502288, 0.118259542621672,
151
+ 0.52218786906451, 0.339233995880932
152
+ ]
153
+
154
+ def checker_n ( n, ref_i, ref_f, inp, ref, lim=nil )
155
+ mrg = MockRandomGenerator.new(ref_i, ref_f)
156
+ my = []
157
+ if lim == :no
158
+ n.times { my << inp.choose(mrg) }
159
+ else
160
+ n.times { my << inp.choose(lim, mrg) }
161
+ end
162
+ assert_equal(ref, my)
163
+ end
164
+
165
+ def checker_5 ( inp, ref, lim=nil )
166
+ checker_n(5, REF_5, REF_F_5, inp, ref, lim)
167
+ end
168
+
169
+ def checker_50 ( inp, ref, lim=nil )
170
+ checker_n(50, REF_50, REF_F_50, inp, ref, lim)
171
+ end
172
+
173
+
174
+
175
+
176
+ def test_integer
177
+ checker_5 Integer, REF_5, 5
178
+ checker_50 Integer, REF_50, 50
179
+ assert(Integer.choose(1000) < 1000)
180
+ end
181
+
182
+ def test_float
183
+ checker_5 Float, REF_F_5, 1.0
184
+ checker_50 Float, REF_F_50, 1.0
185
+ assert(Float.choose(2.0) < 2)
186
+ assert(Float.choose < 1)
187
+ end
188
+
189
+ def test_array_5
190
+ checker_5 [4], [4] * 5, 5
191
+ checker_5 [4, 5], [5, 4, 4, 4, 5], 5
192
+ checker_5 [4, 5, 6], [5, 6, 5, 4, 4], 5
193
+ checker_5 [2, 1, 0, 5, 4, 3], [1, 0, 4, 2, 5], 5
194
+ 10.times { assert(REF_50.include?(REF_50.choose)) }
195
+ end
196
+
197
+ def test_set_5
198
+ checker_5 Set[4], [4] * 5, 5
199
+ checker_5 Set[4, 5], [4, 5, 5, 5, 4], 5
200
+ checker_5 Set[4, 5, 6], [6, 4, 6, 5, 5], 5
201
+ checker_5 Set[2, 1, 0, 5, 4, 3], [0, 1, 3, 5, 2], 5
202
+ set = REF_50.to_set
203
+ 10.times { assert(set.include?(set.choose)) }
204
+ end
205
+
206
+ def test_hash
207
+ checker_5({ 1 => 2 }, [2] * 5, 5)
208
+ checker_5({ 1 => 2, 3 => 4 }, [4, 2, 2, 2, 4], 5)
209
+ end
210
+
211
+ def test_array_50
212
+ checker_50 [4], [4] * 50, 50
213
+ checker_50 [
214
+ 36, 16, 15, 6, 27, 33, 17, 10, 18, 39, 8, 43, 19, 23, 49, 40, 46, 37,
215
+ 9, 41, 35, 0, 38, 26, 22, 4, 7, 25, 21, 12, 42, 45, 28, 5, 31, 24, 34,
216
+ 48, 32, 30, 13, 29, 11, 2, 1, 20, 3, 44, 47, 14
217
+ ], [
218
+ 21, 19, 37, 8, 16, 48, 3, 4, 44, 15, 20, 34, 35, 33, 42, 49, 9, 30,
219
+ 18, 40, 46, 2, 25, 5, 38, 10, 28, 6, 24, 39, 41, 23, 0, 17, 26, 7, 27,
220
+ 13, 1, 43, 14, 12, 11, 22, 45, 47, 31, 36, 32, 29
221
+ ], 50
222
+ end
223
+
224
+ def test_integer_instances
225
+ assert_raise(ArgumentError) { checker_5 0, [], :no }
226
+ checker_5 1, [0] * 5, :no
227
+ checker_5 4, [1, 2, 0, 0, 3], :no
228
+ checker_5 10, REF_5, :no
229
+ assert(1000.choose < 1000)
230
+ end
231
+
232
+ def test_float_instances
233
+ assert_raise(ArgumentError) { checker_5 0.0, [], :no }
234
+ checker_5 1.0, [ 0.187528345035389, 0.368857819121331, 0.06954449811019,
235
+ 0.188887464581057, 0.213757352204993 ], :no
236
+ assert(2.0.choose < 2)
237
+ end
238
+
239
+ def test_integer_range_instances
240
+ checker_5 1..1, [1] * 5, :no
241
+ checker_5 1..2, [2, 1, 1, 1, 2], :no
242
+ checker_5 0..1, [1, 0, 0, 0, 1], :no
243
+ checker_5 0..4, [1, 2, 4, 0, 3], :no
244
+ end
245
+
246
+ class Xs
247
+ include Comparable
248
+ attr_reader :length
249
+ def initialize ( n )
250
+ @length = n
251
+ end
252
+ def succ
253
+ Xs.new(@length.succ)
254
+ end
255
+ def <=> ( rhs )
256
+ @length <=> rhs.length
257
+ end
258
+ def inspect
259
+ 'x' * @length
260
+ end
261
+ end
262
+
263
+ def test_range_instances
264
+ checker_5 'a'..'a', ['a'] * 5, :no
265
+ checker_5 'a'..'b', ['b', 'a', 'a', 'a', 'b'], :no
266
+ checker_5 Xs.new(1)..Xs.new(4), [2, 3, 1, 1, 4].map { |x| Xs.new(x) }, :no
267
+ end
268
+
269
+ end # class ChooseTest
270
+
271
+ end
@@ -0,0 +1,18 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: commands.rb 221 2005-05-09 12:40:57Z ertai $
5
+
6
+ require 'module/autoload_tree'
7
+ require 'pathname_ex'
8
+ require 'abstract'
9
+ require 'commands/helpers'
10
+ require 'mktemp'
11
+ require 'commands/runners'
12
+
13
+
14
+ module Commands
15
+
16
+ autoloaded_module(__FILE__)
17
+
18
+ end # module Commands
@@ -0,0 +1,401 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: command.rb 221 2005-05-09 12:40:57Z ertai $
5
+
6
+ module Commands
7
+
8
+ class Command
9
+
10
+ attr_accessor :command
11
+ attr_accessor :dir
12
+ attr_accessor :input
13
+ attr_accessor :output
14
+ attr_accessor :error
15
+ attr_accessor :arg_list
16
+
17
+ #
18
+ # Construction methods.
19
+ #
20
+
21
+ def initialize ( command_name, *args )
22
+ @command = command_name
23
+ @arg_list = args.dup
24
+ end
25
+
26
+ #
27
+ # Command['wc -l'].sh
28
+ #
29
+ def self.[] ( *args )
30
+ new(*args)
31
+ end
32
+
33
+
34
+
35
+ #
36
+ # Running methods.
37
+ #
38
+
39
+ # Simulate Kernel#system() to run the command (No shell expansion).
40
+ def system
41
+ unless defined? @@fork_runner
42
+ @@fork_runner = Runners::Fork.new
43
+ end
44
+ run(@@fork_runner)
45
+ end
46
+
47
+
48
+ # Use the ExecRunner.
49
+ def exec
50
+ unless defined? @@exec_runner
51
+ @@exec_runner = Runners::Exec.new
52
+ end
53
+ run(@@exec_runner)
54
+ end
55
+
56
+
57
+ # Use Kernel#system() but with a string to have the shell expansion.
58
+ def sh
59
+ Kernel.system(to_sh)
60
+ end
61
+
62
+
63
+ # Use Kernel#exec() but with a string to have the shell expansion.
64
+ def sh!
65
+ Kernel.exec(to_sh)
66
+ end
67
+
68
+
69
+ # Use Kernel#` and return the resulting string.
70
+ def expand
71
+ `#{to_sh}`
72
+ end
73
+
74
+
75
+ # FIXME design me!
76
+ def ruby
77
+ end
78
+
79
+
80
+ # Use a Commands::Runners::Runner and return a Commands::Datas::Data.
81
+ def run ( runner=@runner )
82
+ runner.run(self)
83
+ end
84
+
85
+
86
+
87
+ #
88
+ # Operators.
89
+ #
90
+
91
+
92
+ # Pipe two commands.
93
+ def | ( rhs )
94
+ Pipe.new(self, rhs)
95
+ end
96
+
97
+
98
+ # Chain two commands (like a `;' in shell), and return a new one.
99
+ def + ( rhs )
100
+ Seq.new(self, rhs)
101
+ end
102
+
103
+
104
+ # Return a new command with the given command input.
105
+ def < ( arg )
106
+ cmd = dup
107
+ cmd.input = arg
108
+ cmd
109
+ end
110
+
111
+
112
+ # Return a new command with the given command output.
113
+ def > ( arg )
114
+ cmd = dup
115
+ cmd.output = arg.dup
116
+ cmd.output.open_mode = 'w' if cmd.output.is_a? Pathname
117
+ cmd
118
+ end
119
+
120
+
121
+ # Like > but open the output in append mode.
122
+ def >> ( arg )
123
+ cmd = dup
124
+ cmd.output = arg.dup
125
+ cmd.output.open_mode = 'a' if cmd.output.is_a? Pathname
126
+ cmd
127
+ end
128
+
129
+
130
+ # Add an argument to a command.
131
+ # cmd = Command.new('ls')
132
+ # cmd << '-la'
133
+ # cmd.sh
134
+ def << ( arg )
135
+ @arg_list << arg
136
+ end
137
+
138
+
139
+
140
+ #
141
+ # Misc
142
+ #
143
+
144
+ def arg_list
145
+ @arg_list.dup
146
+ end
147
+
148
+
149
+ def arg_string
150
+ @arg_list.map { |arg| arg.dump }.join(' ').freeze
151
+ end
152
+
153
+
154
+ #
155
+ # Conversion methods
156
+ #
157
+
158
+ def to_s
159
+ str = @command.dump
160
+ arg_str = arg_string
161
+ str += ' ' + arg_str unless arg_str.empty?
162
+ str
163
+ end
164
+
165
+
166
+ def to_sh
167
+ "#{to_s}#{sh_args}"
168
+ end
169
+
170
+
171
+ def sh_args
172
+ args = ''
173
+ args += " < #{@input.to_s.dump}" if @input
174
+ args += " > #{@output.to_s.dump}" if @output
175
+ args += " 2> #{@error.to_s.dump}" if @error
176
+ args
177
+ end
178
+
179
+
180
+ def to_a
181
+ [@command, *@arg_list].freeze
182
+ end
183
+
184
+ end # class Command
185
+
186
+ if $0 == __FILE__
187
+ require 'test/unit'
188
+
189
+ class CommandTest < Test::Unit::TestCase
190
+
191
+ def setup
192
+ @file = TempPath.new
193
+ @file.open('w') { |f| f.puts "bla bla\n foo bar"}
194
+ ENV['TEST_FILE'] = @file.to_s
195
+ @touch = Command.new('touch')
196
+ @cp = Command.new('cp')
197
+ @cat = Command.new('cat')
198
+ @wc = Command.new('wc')
199
+ @dne = Command.new('ThisCommandDoesNotExist')
200
+ @dev_null = Pathname.new('/dev/null')
201
+ end
202
+
203
+ def test_0_initialize
204
+ end
205
+
206
+ def test_self_hook # test_self.[]
207
+ @cat << 'foo' << 'bar'
208
+ assert_equal(@cat.to_a, Command[*%w[cat foo bar]].to_a)
209
+ end
210
+
211
+ def test_system
212
+ TempPath.new do |tmp|
213
+ @touch << tmp.to_s
214
+ @touch.system
215
+ assert_equal(0, $?)
216
+ assert(tmp.exist?)
217
+ end
218
+ end
219
+
220
+ def test_sh_and_pipe
221
+ TempPath.new do |tmp|
222
+ ((@cat | @wc) < @file > tmp).sh
223
+ assert_equal(0, $?)
224
+ assert(tmp.exist?)
225
+ assert_match(/\s*2\s*4\s*17\n/, tmp.read)
226
+ end
227
+ end
228
+
229
+ def test_system_and_pipe
230
+ TempPath.new do |tmp|
231
+ ((@cat | @wc) < @file.open('r+') > tmp).system
232
+ assert_equal(0, $?)
233
+ assert(tmp.exist?)
234
+ assert_match(/\s*2\s*4\s*17\n/, tmp.read)
235
+ end
236
+ end
237
+
238
+ def test_system_is_not_sh
239
+ TempPath.new do |tmp|
240
+ @cat << '$TEST_FILE'
241
+ @cat.error = @dev_null
242
+ (@cat > tmp).system
243
+ assert_not_equal(0, $?)
244
+ assert(!tmp.exist? || tmp.zero?)
245
+ end
246
+ end
247
+
248
+ def test_exec
249
+ TempPath.new do |tmp|
250
+ @cp << @file << tmp
251
+ pid = fork do
252
+ @cp.exec
253
+ end
254
+ Process.waitpid pid
255
+ assert_equal(0, $?)
256
+ assert(tmp.exist?)
257
+ assert_equal(@file.read, tmp.read)
258
+ end
259
+ end
260
+
261
+ def test_exec_not_sh!
262
+ TempPath.new do |tmp|
263
+ @cat << '$TEST_FILE'
264
+ @cat.error = @dev_null
265
+ pid = fork do
266
+ (@cat > tmp).exec
267
+ end
268
+ Process.waitpid pid
269
+ assert_not_equal(0, $?)
270
+ assert(!tmp.exist? || tmp.size.zero?)
271
+ end
272
+ end
273
+
274
+ def test_sh
275
+ TempPath.new do |tmp|
276
+ @cat << '$TEST_FILE'
277
+ (@cat > tmp).sh
278
+ assert_equal(0, $?)
279
+ assert(tmp.exist?)
280
+ assert_equal(@file.read, tmp.read)
281
+ end
282
+
283
+ TempPath.new do |tmp|
284
+ ((@cat | @wc) < @file > tmp).sh
285
+ assert_equal(0, $?)
286
+ assert(tmp.exist?)
287
+ assert_match(/\s*2\s*4\s*17\n/, tmp.read)
288
+ end
289
+ end
290
+
291
+ def test_sh!
292
+ TempPath.new do |tmp|
293
+ @cat << '$TEST_FILE'
294
+ pid = fork do
295
+ (@cat > tmp).sh!
296
+ end
297
+ Process.waitpid pid
298
+ assert_equal(0, $?)
299
+ assert(tmp.exist?)
300
+ assert_equal(@file.read, tmp.read)
301
+ end
302
+ end
303
+
304
+ def test_expand
305
+ @cat << '$TEST_FILE'
306
+ str = (@cat).expand
307
+ assert_equal(0, $?)
308
+ assert_equal(@file.read, str)
309
+
310
+ str = ((@cat | @wc) < @file).expand
311
+ assert_equal(0, $?)
312
+ assert_match(/\s*2\s*4\s*17\n/, str)
313
+ end
314
+
315
+ def test_ruby
316
+ # FIXME
317
+ end
318
+
319
+ def test_pipe # test_|
320
+ assert_kind_of(Pipe, (@cat | @wc) < @file)
321
+ end
322
+
323
+ def test_chain # test_+
324
+ assert_kind_of(Seq, (@cat + @wc) < @file)
325
+ TempPath.new do |tmp|
326
+ TempPath.new do |tmp2|
327
+ ((@cat < @file > tmp) + (@wc < tmp > tmp2)).sh
328
+ assert_equal(0, $?)
329
+ assert(tmp.exist?)
330
+ assert(tmp2.exist?)
331
+ assert_equal(@file.read, tmp.read)
332
+ assert_match(/\s*2\s*4\s*17\n/, tmp2.read)
333
+ end
334
+ end
335
+ end
336
+
337
+ def test_add_input # test_<
338
+ @cat.input = 'foo'
339
+ assert_equal('foo', @cat.input)
340
+ cmd = @cat < 'bar'
341
+ assert_equal('bar', cmd.input)
342
+ assert_not_equal(cmd.object_id, @bar.object_id)
343
+ end
344
+
345
+ def test_add_output # test_>
346
+ @cat.output = 'foo'
347
+ assert_equal('foo', @cat.output)
348
+ cmd = @cat > 'bar'
349
+ assert_equal('bar', cmd.output)
350
+ assert_not_equal(cmd.object_id, @bar.object_id)
351
+ end
352
+
353
+ def test_append_output # test_>>
354
+ @cat.output = 'foo'
355
+ assert_equal('foo', @cat.output)
356
+ cmd = @cat >> 'bar'
357
+ assert_equal('bar', cmd.output)
358
+ assert_not_equal(cmd.object_id, @bar.object_id)
359
+ end
360
+
361
+ def test_arg_list
362
+ assert_equal([], @cp.arg_list)
363
+ @cat << 'foo bar' << 'baz'
364
+ assert_equal(['foo bar', 'baz'], @cat.arg_list)
365
+ end
366
+
367
+ def test_arg_string
368
+ assert_equal('', @cp.arg_string)
369
+ @cat << 'foo bar' << 'baz'
370
+ assert_equal('"foo bar" "baz"', @cat.arg_string)
371
+ end
372
+
373
+ def test_to_s
374
+ assert_equal('"cp"', @cp.to_s)
375
+ @cat << 'foo bar' << 'baz'
376
+ assert_equal('"cat" "foo bar" "baz"', @cat.to_s)
377
+ end
378
+
379
+ def test_to_sh
380
+ assert_equal('"cp" > "ya"', (@cp > 'ya').to_sh)
381
+ @cat << 'foo > bar' << '< baz'
382
+ assert_equal(
383
+ '(("cat" "foo > bar" "< baz" < "yay") | ("cp" > "yoy"))',
384
+ ((@cat | @cp) < 'yay' > 'yoy').to_sh)
385
+ @wc.error = 'foo'
386
+ assert_equal('"wc" 2> "foo"', @wc.to_sh)
387
+ end
388
+
389
+ def test_complex
390
+ TempPath.new do |tmp|
391
+ ls = 'ls'.to_cmd
392
+ wc = 'wc'.to_cmd
393
+ (ls | wc) < @file > tmp
394
+ end
395
+ end
396
+
397
+ end # class CommandTest
398
+
399
+ end
400
+
401
+ end # module Commands