vex 0.2
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 +112 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/config/README +2 -0
- data/config/dependencies.rb +10 -0
- data/config/gem.yml +7 -0
- data/init.rb +36 -0
- data/lib/nokogiri/nokogiri_ext.rb +96 -0
- data/lib/vex.rb +5 -0
- data/lib/vex/action_controller.rb +4 -0
- data/lib/vex/action_controller/verify_action.rb +97 -0
- data/lib/vex/action_controller/whitelisted_actions.rb +45 -0
- data/lib/vex/active_record.rb +3 -0
- data/lib/vex/active_record/__init__.rb +0 -0
- data/lib/vex/active_record/advisory_lock.rb +11 -0
- data/lib/vex/active_record/advisory_lock/mysql_adapter.rb +16 -0
- data/lib/vex/active_record/advisory_lock/sqlite_adapter.rb +78 -0
- data/lib/vex/active_record/belongs_to_many.rb +143 -0
- data/lib/vex/active_record/find_by_extension.rb +70 -0
- data/lib/vex/active_record/gem.rb +8 -0
- data/lib/vex/active_record/lite_table.rb +139 -0
- data/lib/vex/active_record/lite_view.rb +140 -0
- data/lib/vex/active_record/mass_load.rb +65 -0
- data/lib/vex/active_record/mysql_backup.rb +21 -0
- data/lib/vex/active_record/plugins/default_value_for/LICENSE.TXT +19 -0
- data/lib/vex/active_record/plugins/default_value_for/README.rdoc +421 -0
- data/lib/vex/active_record/plugins/default_value_for/Rakefile +6 -0
- data/lib/vex/active_record/plugins/default_value_for/init.rb +91 -0
- data/lib/vex/active_record/plugins/default_value_for/test.rb +279 -0
- data/lib/vex/active_record/plugins/default_value_for/test.sqlite3 +0 -0
- data/lib/vex/active_record/random_id.rb +56 -0
- data/lib/vex/active_record/resolver.rb +49 -0
- data/lib/vex/active_record/serialize_hash.rb +125 -0
- data/lib/vex/active_record/to_html.rb +53 -0
- data/lib/vex/active_record/validate.rb +76 -0
- data/lib/vex/active_record/validation_error_ext.rb +68 -0
- data/lib/vex/base.rb +2 -0
- data/lib/vex/base/app.rb +75 -0
- data/lib/vex/base/array/at_random.rb +17 -0
- data/lib/vex/base/array/cross.rb +26 -0
- data/lib/vex/base/array/each_batch.rb +32 -0
- data/lib/vex/base/array/parallel_map.rb +98 -0
- data/lib/vex/base/deprecation.rb +41 -0
- data/lib/vex/base/enumerable/deep.rb +95 -0
- data/lib/vex/base/enumerable/enumerable_ext.rb +59 -0
- data/lib/vex/base/enumerable/progress.rb +71 -0
- data/lib/vex/base/filesystem/fast_copy.rb +61 -0
- data/lib/vex/base/filesystem/grep.rb +34 -0
- data/lib/vex/base/filesystem/lock.rb +43 -0
- data/lib/vex/base/filesystem/lock.rb.test.lck +0 -0
- data/lib/vex/base/filesystem/lock.rb.test.pid +1 -0
- data/lib/vex/base/filesystem/make_dirs.rb +94 -0
- data/lib/vex/base/filesystem/parse_filename.rb +36 -0
- data/lib/vex/base/filesystem/tmp_file.rb +87 -0
- data/lib/vex/base/filesystem/write.rb +43 -0
- data/lib/vex/base/hash/compact.rb +38 -0
- data/lib/vex/base/hash/cross.rb +117 -0
- data/lib/vex/base/hash/easy_access.rb +141 -0
- data/lib/vex/base/hash/ensure_keys.rb +18 -0
- data/lib/vex/base/hash/extract.rb +71 -0
- data/lib/vex/base/hash/extras.rb +62 -0
- data/lib/vex/base/hash/inspect.rb +17 -0
- data/lib/vex/base/hash/simple_access_methods.rb +74 -0
- data/lib/vex/base/invalid_argument/invalid_argument.rb +97 -0
- data/lib/vex/base/local_conf.rb +35 -0
- data/lib/vex/base/net/http_ext.rb +227 -0
- data/lib/vex/base/net/socket_ext.rb +43 -0
- data/lib/vex/base/object/insp.rb +123 -0
- data/lib/vex/base/object/multiple_attributes.rb +58 -0
- data/lib/vex/base/object/singleton_methods.rb +23 -0
- data/lib/vex/base/object/with_benchmark.rb +110 -0
- data/lib/vex/base/range_array.rb +40 -0
- data/lib/vex/base/range_ext.rb +28 -0
- data/lib/vex/base/safe_token.rb +156 -0
- data/lib/vex/base/string/string_ext.rb +136 -0
- data/lib/vex/base/thread/deferred.rb +52 -0
- data/lib/vex/base/thread/sleep.rb +11 -0
- data/lib/vex/base/time/date_ext.rb +12 -0
- data/lib/vex/boot.rb +40 -0
- data/lib/vex/boot/array.rb +22 -0
- data/lib/vex/boot/blank.rb +41 -0
- data/lib/vex/boot/string.rb +60 -0
- data/migration/create_request_log.rb +28 -0
- data/r.rb +35 -0
- data/script/console +19 -0
- data/script/rebuild +7 -0
- data/tasks/echoe.rake +52 -0
- data/tasks/validate_db.rake +14 -0
- data/test/ar.rb +30 -0
- data/test/auto.rb +31 -0
- data/test/base-tests/local_conf.rb +25 -0
- data/test/base.rb +2 -0
- data/test/boot.rb +3 -0
- data/test/config/local.defaults.yml +4 -0
- data/test/config/local.yml +8 -0
- data/test/test.sqlite3 +0 -0
- data/test/test.sqlite3.Class#create.lck +0 -0
- data/test/test.sqlite3.Class#create.lck.lck +0 -0
- data/test/test.sqlite3.Class#create.lck.pid +1 -0
- data/test/test.sqlite3.Class#create.pid +1 -0
- data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck +0 -0
- data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck.lck +0 -0
- data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck.pid +1 -0
- data/test/test.sqlite3.LiteView.make.holders__view_dummy.pid +1 -0
- data/test/test.sqlite3.vex.lck +0 -0
- data/test/test_helper.rb +49 -0
- data/test/tmp/copy.dat +1 -0
- data/test/tmp/lock.sqlite3 +0 -0
- data/test/tmp/lock.sqlite3.etest.lck +0 -0
- data/test/tmp/lock.sqlite3.etest.pid +1 -0
- data/test/tmp/somedata.dat +61 -0
- data/vex.gemspec +49 -0
- data/vex.tmproj +186 -0
- metadata +305 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Array::EachBatch
|
|
2
|
+
def each_batch(batch_size = 1000, &block)
|
|
3
|
+
raise "Invalid parameter #{batch_size.inspect}, must be a Fixnum" unless batch_size.is_a?(Fixnum)
|
|
4
|
+
|
|
5
|
+
data = dup
|
|
6
|
+
begin
|
|
7
|
+
batch = data.slice!(0..(batch_size-1))
|
|
8
|
+
yield batch
|
|
9
|
+
end until data.empty?
|
|
10
|
+
self
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
Array.send :include, Array::EachBatch
|
|
15
|
+
|
|
16
|
+
module Array::Cross::Etest
|
|
17
|
+
def test_each_batch
|
|
18
|
+
r = []
|
|
19
|
+
[1,2,3,4,5,6,7,8,9].each_batch 3 do |batch|
|
|
20
|
+
r << batch
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
assert_equal( [[1,2,3],[4,5,6],[7,8,9]], r)
|
|
24
|
+
|
|
25
|
+
r = []
|
|
26
|
+
[1,2,3,4,5,6,7].each_batch 3 do |batch|
|
|
27
|
+
r << batch
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
assert_equal( [[1,2,3],[4,5,6],[7]], r)
|
|
31
|
+
end
|
|
32
|
+
end if VEX_TEST == "base"
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require "timeout"
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# a simple (really really simple) map-in-parallel multithreaded mapper.
|
|
5
|
+
module Array::ParallelMap
|
|
6
|
+
|
|
7
|
+
def self.timeout(opts, &block)
|
|
8
|
+
return yield unless opts[:timeout]
|
|
9
|
+
begin
|
|
10
|
+
Timeout.timeout(opts[:timeout], &block)
|
|
11
|
+
rescue Timeout::Error
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def peach_with_index(opts = {}, &block)
|
|
16
|
+
return [] if empty?
|
|
17
|
+
|
|
18
|
+
threads = []
|
|
19
|
+
|
|
20
|
+
each_with_index do |data, index|
|
|
21
|
+
threads << Thread.new {
|
|
22
|
+
Array::ParallelMap.timeout(opts) { yield(data, index) }
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
threads.each do |thread| thread.join end
|
|
27
|
+
self
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def peach(opts = {}, &block)
|
|
31
|
+
peach_with_index(opts) do |data, index|
|
|
32
|
+
yield(data)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def pmap(opts = {}, &block)
|
|
37
|
+
semaphore = Mutex.new
|
|
38
|
+
|
|
39
|
+
results = []
|
|
40
|
+
|
|
41
|
+
peach_with_index(opts) do |data, index|
|
|
42
|
+
r = yield(data)
|
|
43
|
+
semaphore.synchronize { results[index] = r }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
results
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
Array.send :include, Array::ParallelMap
|
|
51
|
+
|
|
52
|
+
module Array::ParallelMap::Etest
|
|
53
|
+
MAX = 1000
|
|
54
|
+
|
|
55
|
+
def calculate(repeat, method)
|
|
56
|
+
(1..repeat).to_a.send(method) do |p|
|
|
57
|
+
(1..MAX).inject(0) do |sum, i|
|
|
58
|
+
sum + p * i
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def calculate_serial(repeat)
|
|
64
|
+
calculate(repeat, :map)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def calculate_parallel(repeat)
|
|
68
|
+
calculate(repeat, :pmap)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_pmap
|
|
72
|
+
serial = calculate_serial(4)
|
|
73
|
+
parallel = calculate_parallel(4)
|
|
74
|
+
assert_equal(serial, parallel)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def test_peach
|
|
78
|
+
semaphore = Mutex.new
|
|
79
|
+
|
|
80
|
+
results = []
|
|
81
|
+
|
|
82
|
+
array = [ 1, 2, 3, 4]
|
|
83
|
+
r = array.peach do |p|
|
|
84
|
+
semaphore.synchronize { results << p }
|
|
85
|
+
end
|
|
86
|
+
assert_equal(array, results.sort)
|
|
87
|
+
assert_equal(array, r)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_pmap_timeout
|
|
91
|
+
r = [1, 2].pmap(:timeout => 0.1) do |p|
|
|
92
|
+
sleep 0.2
|
|
93
|
+
p * p
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
assert_equal([], r)
|
|
97
|
+
end
|
|
98
|
+
end if VEX_TEST == "base"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#
|
|
2
|
+
# short inspect method on all objects.
|
|
3
|
+
#
|
|
4
|
+
# "abcdefghijklmnopabcdefghijklmnopabcdefghijklmnopabcdefghijklmnop".insp
|
|
5
|
+
# -> "abcdefghijklmnopabcdefghijk..."
|
|
6
|
+
# Model.find(1).insp
|
|
7
|
+
# -> "<Model#1>"
|
|
8
|
+
|
|
9
|
+
module Deprecation
|
|
10
|
+
def self.quiet
|
|
11
|
+
@quiet = true
|
|
12
|
+
yield
|
|
13
|
+
ensure
|
|
14
|
+
@quiet = false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.seen
|
|
18
|
+
@seen ||= {}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.report(msg, instead=nil)
|
|
22
|
+
return if App.env == "production"
|
|
23
|
+
return if @quiet
|
|
24
|
+
return if seen[[msg, instead]]
|
|
25
|
+
|
|
26
|
+
seen[[msg, instead]] = true
|
|
27
|
+
|
|
28
|
+
msg = "#{msg} is deprecated"
|
|
29
|
+
msg += "; use #{instead} instead" if instead
|
|
30
|
+
msg += ". From\n\t" + caller[1,4].join("\n\t")
|
|
31
|
+
STDERR.puts msg
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
module Deprecation::Etest
|
|
36
|
+
def test_report
|
|
37
|
+
STDERR.expects(:puts)
|
|
38
|
+
Deprecation.report "Hey"
|
|
39
|
+
Deprecation.report "Hey"
|
|
40
|
+
end
|
|
41
|
+
end if VEX_TEST == "base"
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module Deep
|
|
2
|
+
KEYS = 0x01
|
|
3
|
+
VALUES = 0x02
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# deep mapping
|
|
7
|
+
def self.map(o, mode, &block)
|
|
8
|
+
case o
|
|
9
|
+
when Hash
|
|
10
|
+
o.inject({}) do |hash, (k,v)|
|
|
11
|
+
k = yield(k) if (mode & KEYS) != 0
|
|
12
|
+
v = map(v, mode, &block)
|
|
13
|
+
hash.update k => v
|
|
14
|
+
hash
|
|
15
|
+
end
|
|
16
|
+
when Array
|
|
17
|
+
if mode & VALUES
|
|
18
|
+
o.map do |v|
|
|
19
|
+
map(v, mode, &block)
|
|
20
|
+
end
|
|
21
|
+
else
|
|
22
|
+
o.dup
|
|
23
|
+
end
|
|
24
|
+
else
|
|
25
|
+
if (mode & VALUES) != 0
|
|
26
|
+
yield o
|
|
27
|
+
else
|
|
28
|
+
o
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
#
|
|
34
|
+
# deep reject
|
|
35
|
+
def self.reject(o, mode, &block)
|
|
36
|
+
case o
|
|
37
|
+
when Hash
|
|
38
|
+
o.inject({}) do |hash, (k,v)|
|
|
39
|
+
next hash if (mode & KEYS) && yield(k)
|
|
40
|
+
v = reject v, mode, &block
|
|
41
|
+
next hash if (mode & VALUES) && yield(v)
|
|
42
|
+
hash.update k => v
|
|
43
|
+
hash
|
|
44
|
+
end
|
|
45
|
+
when Array
|
|
46
|
+
if mode & VALUES
|
|
47
|
+
o.inject([]) do |r, v|
|
|
48
|
+
v = reject(v, mode, &block)
|
|
49
|
+
r << v unless yield(v)
|
|
50
|
+
end
|
|
51
|
+
else
|
|
52
|
+
o.dup
|
|
53
|
+
end
|
|
54
|
+
else
|
|
55
|
+
o
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
module Enumerable
|
|
61
|
+
KEYS = Deep::KEYS
|
|
62
|
+
VALUES = Deep::VALUES
|
|
63
|
+
|
|
64
|
+
def reject_blanks
|
|
65
|
+
Deep.reject(self, KEYS | VALUES) do |s|
|
|
66
|
+
s.blank?
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def camelize
|
|
71
|
+
Deep.map(self, KEYS) do |s|
|
|
72
|
+
s.to_s.camelize
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
module Deep::Etest
|
|
78
|
+
def test_reject_blanks
|
|
79
|
+
h = { :a => "a", :b_c => { :d => nil, :video_test => "video_test "}, "x" => nil, "y" => [] }
|
|
80
|
+
expected = { :a=>"a", :b_c => { :video_test => "video_test " }}
|
|
81
|
+
assert_equal(expected, h.reject_blanks)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def test_camelized_keys
|
|
85
|
+
h = { :a => "a", :b_c => { :d => "dd", :video_test => "video_test "}}
|
|
86
|
+
expected = { "A"=>"a", "BC" => { "VideoTest" => "video_test ", "D" => "dd" }}
|
|
87
|
+
assert_equal(expected, h.camelize)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_missin_block
|
|
91
|
+
assert_raise(LocalJumpError) {
|
|
92
|
+
Deep.reject(%w(1 2), 3)
|
|
93
|
+
}
|
|
94
|
+
end
|
|
95
|
+
end if VEX_TEST == "base"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Enumerable
|
|
2
|
+
def any_not?(&block)
|
|
3
|
+
not all? { |e| yield(e) }
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def none?(&block)
|
|
7
|
+
not any? { |e| yield(e) }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def stable_sort_by
|
|
11
|
+
# NOTE: if soort_by wouldn't enumerate the array members from
|
|
12
|
+
# the beginning this would fail.
|
|
13
|
+
i=0
|
|
14
|
+
sort_by { |x| [ yield(x), i+=1 ] }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def hmap(&block)
|
|
18
|
+
inject({}) { |hash, obj| hash[obj] = yield(obj); hash }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
module Enumerable::Etest
|
|
23
|
+
def test_stable_sort_by
|
|
24
|
+
data = [[1, 'b'], [1, 'c'], [0, 'b'], [0, 'a']]
|
|
25
|
+
|
|
26
|
+
# This might or might not fail, but is not guaranteed to do so:
|
|
27
|
+
# assert_equal [[0, 'b'], [0, 'a'], [ 1, 'b'], [1, 'c']], data.stable_sort_by { |t| t[0] }
|
|
28
|
+
assert_equal [[0, 'b'], [0, 'a'], [ 1, 'b'], [1, 'c']], data.stable_sort_by { |t| t[0] }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_any_none(&block)
|
|
32
|
+
assert_equal(false, [ 1, 2, true, false ].any?(&:nil?))
|
|
33
|
+
assert_equal(true, [ 1, 2, true, false ].none?(&:nil?))
|
|
34
|
+
assert_equal(true, [ 1, 2, true, false, nil ].any?(&:nil?))
|
|
35
|
+
assert_equal(false, [ 1, 2, true, false, nil ].none?(&:nil?))
|
|
36
|
+
|
|
37
|
+
assert_equal(true, [ nil ].any?(&:nil?))
|
|
38
|
+
assert_equal(false, [ 1 ].any?(&:nil?))
|
|
39
|
+
assert_equal(false, [ ].any?(&:nil?))
|
|
40
|
+
|
|
41
|
+
assert_equal(false, [ nil ].none?(&:nil?))
|
|
42
|
+
assert_equal(true, [ 1 ].none?(&:nil?))
|
|
43
|
+
assert_equal(true, [ ].none?(&:nil?))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_any_not_all(&block)
|
|
47
|
+
assert_equal(true, [ 1, 2, true, false ].any_not?(&:nil?))
|
|
48
|
+
assert_equal(true, [ 1, 2, nil ].any_not?(&:nil?))
|
|
49
|
+
assert_equal(false, [ nil ].any_not?(&:nil?))
|
|
50
|
+
assert_equal(true, [ 1 ].any_not?(&:nil?))
|
|
51
|
+
assert_equal(false, [ ].any_not?(&:nil?))
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_hmap
|
|
55
|
+
h = %w(1 2 3)
|
|
56
|
+
|
|
57
|
+
assert_equal({ "1" => 1, "2" => 4, "3" => 9}, h.hmap do |line| line.to_i * line.to_i end)
|
|
58
|
+
end
|
|
59
|
+
end if VEX_TEST == "base"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Enumerable
|
|
2
|
+
class Progress
|
|
3
|
+
def initialize(base, count=nil)
|
|
4
|
+
@base = base
|
|
5
|
+
@idx = 0
|
|
6
|
+
@count = count
|
|
7
|
+
@count ||= base.is_a?(Range) ? (base.max - base.min + 1) : length
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def method_missing(sym, *args)
|
|
11
|
+
return @base.send(sym, *args) unless block_given?
|
|
12
|
+
|
|
13
|
+
r = @base.send sym, *args do |*args|
|
|
14
|
+
begin
|
|
15
|
+
yield *args
|
|
16
|
+
ensure
|
|
17
|
+
@idx += 1
|
|
18
|
+
on_progress(@idx, @count)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class ConsoleProgress < Progress
|
|
25
|
+
def initialize(base, count=nil)
|
|
26
|
+
@start, @last = Time.now, nil
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def print_line(s)
|
|
33
|
+
print s
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def on_progress(idx, count)
|
|
37
|
+
if idx == count
|
|
38
|
+
print_line("\r#{"%.1f%%" % 100}#{" " * 40}\n")
|
|
39
|
+
return
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
now = Time.now
|
|
43
|
+
return if @last && now - @last <= 1
|
|
44
|
+
|
|
45
|
+
@last = now
|
|
46
|
+
span = @last - @start
|
|
47
|
+
remaining = ((count * 1.0 / idx) - 1) * span
|
|
48
|
+
|
|
49
|
+
print_line "\r#{"%.1f%%" % ((100.0 * idx) / count)}\t#{" %.1f secs remaining " % remaining}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class Progress
|
|
54
|
+
IMPLEMENTATIONS = {
|
|
55
|
+
:console => ConsoleProgress
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def with_progress(impl = :console)
|
|
60
|
+
Progress::IMPLEMENTATIONS[impl].new(self)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
module Enumerable::Etest
|
|
65
|
+
def test_with_progress
|
|
66
|
+
Enumerable::ConsoleProgress.any_instance.stubs(:print_line).returns(nil)
|
|
67
|
+
|
|
68
|
+
r = [ 1, 2 ].with_progress.map do |s| s * s end
|
|
69
|
+
assert_equal( [ 1, 4], r)
|
|
70
|
+
end
|
|
71
|
+
end if VEX_TEST == "base"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module FileUtils::FastCopy
|
|
2
|
+
# fast_copy a file: This hardlinks the source file to the destfile,
|
|
3
|
+
# if possible. src must refer to a file; dest must refer to a file
|
|
4
|
+
# or not exist at all.
|
|
5
|
+
def fast_copy(src, dest)
|
|
6
|
+
src_stat = File.stat(src)
|
|
7
|
+
invalid_argument!(src) unless src_stat.file?
|
|
8
|
+
|
|
9
|
+
dest_stat = begin
|
|
10
|
+
File.stat(dest)
|
|
11
|
+
rescue Errno::ENOENT
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
invalid_argument!(dest) unless !dest_stat || dest_stat.file?
|
|
15
|
+
|
|
16
|
+
dest_dev = dest_stat ? dest_stat.dev : begin
|
|
17
|
+
dest_dir = File.dirname(File.expand_path(dest))
|
|
18
|
+
File.stat(dest_dir).dev
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if src_stat.dev == dest_dev
|
|
22
|
+
File.unlink(dest) if File.exists?(dest)
|
|
23
|
+
File.link src, dest
|
|
24
|
+
else
|
|
25
|
+
FileUtils.copy src, dest
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
FileUtils.extend FileUtils::FastCopy
|
|
31
|
+
|
|
32
|
+
module FileUtils::FastCopy::Etest
|
|
33
|
+
def test_fast_copy
|
|
34
|
+
assert File.exist?(__FILE__)
|
|
35
|
+
File.unlink("tmp/somedata.dat") if File.exist?("tmp/somedata.dat")
|
|
36
|
+
|
|
37
|
+
assert !File.exist?("tmp/somedata.dat")
|
|
38
|
+
FileUtils.fast_copy __FILE__, "tmp/somedata.dat"
|
|
39
|
+
assert_equal File.read("tmp/somedata.dat"), File.read(__FILE__)
|
|
40
|
+
|
|
41
|
+
File.unlink("tmp/somedata.dat")
|
|
42
|
+
File.touch("tmp/somedata.dat")
|
|
43
|
+
assert_not_equal File.size("tmp/somedata.dat"), File.size(__FILE__)
|
|
44
|
+
FileUtils.fast_copy __FILE__, "tmp/somedata.dat"
|
|
45
|
+
assert_equal File.size("tmp/somedata.dat"), File.size(__FILE__)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def test_fast_copy_failures
|
|
49
|
+
assert_raise(Errno::ENOENT) {
|
|
50
|
+
FileUtils.fast_copy "fixtures/somedata.dat.nonexisting", "tmp/somedata.dat"
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
assert_raise(Errno::ENOENT) {
|
|
54
|
+
FileUtils.fast_copy "fixtures/somedata.dat.nonexisting", "tmp"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
assert_raise(Errno::ENOENT) {
|
|
58
|
+
FileUtils.fast_copy __FILE__, "tmp/nonexisting/dir"
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
end if VEX_TEST == "base"
|