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,53 @@
|
|
|
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: session_server.rb 91 2005-01-09 22:24:40Z polrop $
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
require 'drb/extserv'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
module DRb
|
|
13
|
+
|
|
14
|
+
class SessionServer < ExtServ
|
|
15
|
+
|
|
16
|
+
attr_reader :name
|
|
17
|
+
|
|
18
|
+
alias sid name
|
|
19
|
+
|
|
20
|
+
end # class SessionServer
|
|
21
|
+
|
|
22
|
+
end # module DRb
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __FILE__ == $0
|
|
26
|
+
|
|
27
|
+
require 'drb/drb'
|
|
28
|
+
require 'drb/extserv'
|
|
29
|
+
require 'yaml'
|
|
30
|
+
require 'tempfile'
|
|
31
|
+
|
|
32
|
+
class Foo
|
|
33
|
+
|
|
34
|
+
def hello
|
|
35
|
+
'hello'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def salut
|
|
39
|
+
'salut'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end # class SessionManagerTest
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
raise "usage: #{$0} <uri> <name>" unless ARGV.size == 2
|
|
46
|
+
uri = ARGV.shift
|
|
47
|
+
name = ARGV.shift
|
|
48
|
+
|
|
49
|
+
server = DRb::DRbServer.new("druby://localhost:0", Foo.new, {})
|
|
50
|
+
ext_srv = DRb::SessionServer.new(uri, name, server)
|
|
51
|
+
server.thread.join
|
|
52
|
+
|
|
53
|
+
end
|
data/ruby_ex/dtime.rb
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
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: dtime.rb 146 2005-02-01 11:02:42Z polrop $
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
require 'module/attr_once'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DTime
|
|
13
|
+
|
|
14
|
+
def initialize(delta)
|
|
15
|
+
@delta = delta.abs
|
|
16
|
+
@min, @sec = @delta.divmod(60)
|
|
17
|
+
@hour, @min = @min.floor.divmod(60)
|
|
18
|
+
@day, @hour = @hour.divmod(24)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
attr_reader :delta, :sec, :min, :hour, :day
|
|
22
|
+
|
|
23
|
+
def to_s
|
|
24
|
+
@delta.to_s.freeze
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def inspect
|
|
28
|
+
"#@day days #@hour hours #@min mins #@sec secs".freeze
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_a
|
|
32
|
+
[ @day, @hour, @min, @sec ].freeze
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def to_i
|
|
36
|
+
@delta.to_i
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
alias to_f delta
|
|
40
|
+
|
|
41
|
+
def hash
|
|
42
|
+
@delta.hash
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def to_hash
|
|
46
|
+
{ :days => @day, :hours => @hour, :mins => @min, :secs => @sec }.freeze
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def floor
|
|
50
|
+
@delta.floor
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def round
|
|
54
|
+
@delta.round
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def to_yaml(opts={})
|
|
58
|
+
((@day != 0 ? "#@day days " : '') +
|
|
59
|
+
(@hour != 0 ? "#@hour hours " : '') +
|
|
60
|
+
(@min != 0 ? "#@min mins " : '') +
|
|
61
|
+
"#@sec secs").to_yaml(opts)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
attr_once :to_s, :inspect, :to_a, :to_i, :hash, :to_hash, :floor,
|
|
65
|
+
:round, :to_yaml
|
|
66
|
+
|
|
67
|
+
end # class DTime
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if defined? TEST_MODE or __FILE__ == $0
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
require 'test/unit/ui/yaml/testrunner'
|
|
74
|
+
require 'yaml'
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class DTimeTest < Test::Unit::TestCase
|
|
78
|
+
|
|
79
|
+
def test_simple
|
|
80
|
+
d = DTime.new(260.33)
|
|
81
|
+
assert_equal(260, d.delta.floor)
|
|
82
|
+
assert_equal(20, d.sec.floor)
|
|
83
|
+
assert_equal(4, d.min)
|
|
84
|
+
assert_equal(0, d.hour)
|
|
85
|
+
assert_equal(0, d.day)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_complex
|
|
89
|
+
d = DTime.new(265678.42000)
|
|
90
|
+
assert_equal(265678, d.delta.floor)
|
|
91
|
+
assert_equal(58, d.sec.floor)
|
|
92
|
+
assert_equal(47, d.min)
|
|
93
|
+
assert_equal(1, d.hour)
|
|
94
|
+
assert_equal(3, d.day)
|
|
95
|
+
assert_equal([ 3, 1, 47 ], d.to_a[0..2])
|
|
96
|
+
assert_equal(58, d.to_a[3].floor)
|
|
97
|
+
h = d.to_hash
|
|
98
|
+
assert_equal(3, h[:days])
|
|
99
|
+
assert_equal(1, h[:hours])
|
|
100
|
+
assert_equal(47, h[:mins])
|
|
101
|
+
assert_equal(58, h[:secs].floor)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def test_conversion
|
|
105
|
+
d = DTime.new(260.75)
|
|
106
|
+
assert_equal('260.75', d.to_s)
|
|
107
|
+
assert_equal('0 days 0 hours 4 mins 20.75 secs', d.inspect)
|
|
108
|
+
assert_equal(260, d.to_f.floor)
|
|
109
|
+
assert_equal(260, d.to_i)
|
|
110
|
+
assert_equal(260, d.floor)
|
|
111
|
+
assert_equal(261, d.round)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_negative
|
|
115
|
+
d = DTime.new(-265678.42000)
|
|
116
|
+
assert_equal(265678, d.delta.floor)
|
|
117
|
+
assert_equal(58, d.sec.floor)
|
|
118
|
+
assert_equal(47, d.min)
|
|
119
|
+
assert_equal(1, d.hour)
|
|
120
|
+
assert_equal(3, d.day)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_marshal
|
|
124
|
+
d = DTime.new(-265678.42000)
|
|
125
|
+
assert_equal(d.floor, Marshal.load(Marshal.dump(d)).floor)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def test_to_yaml
|
|
129
|
+
d = DTime.new(265678.42000)
|
|
130
|
+
assert_equal('--- 3 days 1 hours 47 mins 58.4199999999837 secs', d.to_yaml)
|
|
131
|
+
d = DTime.new(5678.42000)
|
|
132
|
+
assert_equal('--- 1 hours 34 mins 38.4200000000001 secs', d.to_yaml)
|
|
133
|
+
d = DTime.new(158.42000)
|
|
134
|
+
assert_equal('--- 2 mins 38.42 secs', d.to_yaml)
|
|
135
|
+
d = DTime.new(58.42000)
|
|
136
|
+
assert_equal('--- 58.42 secs', d.to_yaml)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end # class DTimeTest
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Copyright: Copyright (c) 2005 Nicolas Pouillard. All rights reserved.
|
|
2
|
+
# Author: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
|
3
|
+
# License: Gnu General Public License.
|
|
4
|
+
|
|
5
|
+
# $LastChangedBy: ertai $
|
|
6
|
+
# $Id: dumpable_proc.rb 190 2005-04-04 14:46:40Z ertai $
|
|
7
|
+
|
|
8
|
+
require 'yaml'
|
|
9
|
+
require 'delegate'
|
|
10
|
+
|
|
11
|
+
class DumpableProc < DelegateClass(Proc)
|
|
12
|
+
|
|
13
|
+
def initialize ( str )
|
|
14
|
+
@str = str.freeze
|
|
15
|
+
super(eval("proc { #@str }"))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def _dump ( depth )
|
|
19
|
+
Marshal.dump([self.class, @str])
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self._load ( data )
|
|
23
|
+
klass, str = Marshal.load(data)
|
|
24
|
+
klass.new(str)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_yaml ( opts={} )
|
|
28
|
+
"#{to_yaml_type} #@str"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_s
|
|
32
|
+
@str
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def to_yaml_type
|
|
36
|
+
'!proc'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
YAML.add_builtin_type('!proc') do |type, val|
|
|
42
|
+
DumpableProc.new(val.to_s)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if defined? TEST_MODE or $0 == __FILE__
|
|
46
|
+
|
|
47
|
+
require 'test/unit'
|
|
48
|
+
|
|
49
|
+
class DumpableProcTest < Test::Unit::TestCase
|
|
50
|
+
|
|
51
|
+
def test_simple
|
|
52
|
+
p = DumpableProc.new('|x| 3 + x')
|
|
53
|
+
assert_equal(7, p[4])
|
|
54
|
+
str = nil
|
|
55
|
+
assert_nothing_raised { str = Marshal.dump(p) }
|
|
56
|
+
p2 = nil
|
|
57
|
+
assert_nothing_raised { p2 = Marshal.load(str) }
|
|
58
|
+
assert_equal(9, p2[6])
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
# Revision:: $Id: exception.rb 200 2005-04-22 22:55:31Z ertai $
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Exception
|
|
8
|
+
|
|
9
|
+
#FIXME: write a ruby_pp which print exception backtrace exactly as ruby does
|
|
10
|
+
# by cuting long and repetitive backtrace.
|
|
11
|
+
|
|
12
|
+
def long_pp
|
|
13
|
+
str = short_pp + "\n"
|
|
14
|
+
backtrace[1..-1].each { |x| str += " from #{x}\n" } if backtrace
|
|
15
|
+
str.chomp!
|
|
16
|
+
str
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def short_pp
|
|
20
|
+
if backtrace.nil?
|
|
21
|
+
tiny_pp
|
|
22
|
+
else
|
|
23
|
+
"#{backtrace[0]}: #{tiny_pp}"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def tiny_pp
|
|
28
|
+
exc_name = inspect.sub(/^#<(\w+):.+$/, '\1')
|
|
29
|
+
"#{self} (#{exc_name})"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end # class Exception
|
data/ruby_ex/filetype.rb
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
require 'pathname_ex'
|
|
2
|
+
require 'abstract'
|
|
3
|
+
|
|
4
|
+
module FileType
|
|
5
|
+
|
|
6
|
+
@@subclasses = []
|
|
7
|
+
|
|
8
|
+
def self.register ( klass )
|
|
9
|
+
@@subclasses << klass
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class Generic
|
|
13
|
+
include Abstract
|
|
14
|
+
|
|
15
|
+
attr_reader :path, :base, :ext
|
|
16
|
+
|
|
17
|
+
def initialize ( path )
|
|
18
|
+
@path = Pathname.new(path)
|
|
19
|
+
re = self.class.extension
|
|
20
|
+
raise ArgumentError, "bad class #{self.class}" if re.nil?
|
|
21
|
+
unless @path.to_s =~ re
|
|
22
|
+
raise ArgumentError, "#{@path} do not match /#{re.source}/"
|
|
23
|
+
end
|
|
24
|
+
@base, @ext = $`, $&
|
|
25
|
+
if @ext.empty?
|
|
26
|
+
@base = self
|
|
27
|
+
else
|
|
28
|
+
@base = FileType.guess(@base)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def extsplit
|
|
33
|
+
[@base, @ext]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.inherited ( klass )
|
|
37
|
+
FileType.register(klass)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def to_s
|
|
41
|
+
@path.to_s
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.extension
|
|
45
|
+
const_get(:EXTENSION)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.match_type ( path, max, best )
|
|
49
|
+
ext_re = self.extension
|
|
50
|
+
if path.to_s =~ ext_re and $&.size > max
|
|
51
|
+
return [$&.size, self]
|
|
52
|
+
end
|
|
53
|
+
return [max, best]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def + ( arg )
|
|
57
|
+
@path + arg.to_s
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end # class Generic
|
|
61
|
+
|
|
62
|
+
class Unknown < Generic
|
|
63
|
+
include Concrete
|
|
64
|
+
EXTENSION = /(\.[^.\/]+)?$/
|
|
65
|
+
end # class Unknown
|
|
66
|
+
|
|
67
|
+
class ExtractError < Exception
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
module Extractable
|
|
71
|
+
|
|
72
|
+
def self.included ( aClass )
|
|
73
|
+
|
|
74
|
+
aClass.module_eval do
|
|
75
|
+
|
|
76
|
+
def mk_cmd
|
|
77
|
+
base, ext = @base.extsplit
|
|
78
|
+
@tmp = TempPath.new(base.path.basename, ext)
|
|
79
|
+
cmd = self.class.const_get(:EXTRACT_COMMAND).gsub(/%I/, @path.to_s)
|
|
80
|
+
cmd.gsub!(/%O/, @tmp.to_s)
|
|
81
|
+
cmd
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def extract
|
|
85
|
+
cmd = mk_cmd
|
|
86
|
+
unless system(cmd)
|
|
87
|
+
@tmp.rmtree if @tmp.exist?
|
|
88
|
+
err = "
|
|
89
|
+
|Cannot extract a file:
|
|
90
|
+
| path: #{to_s}
|
|
91
|
+
| type: #{self.class}
|
|
92
|
+
| command: #{cmd}
|
|
93
|
+
| exit status: #{$? >> 8}
|
|
94
|
+
"
|
|
95
|
+
raise ExtractError, err.gsub(/^\s*|/, '')
|
|
96
|
+
end
|
|
97
|
+
FileType.guess(@tmp)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
alias :default :extract
|
|
101
|
+
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end # module Extractable
|
|
107
|
+
|
|
108
|
+
# FIXME Use the zlib if gzip not available.
|
|
109
|
+
class Gz < Generic
|
|
110
|
+
include Extractable
|
|
111
|
+
include Concrete
|
|
112
|
+
EXTENSION = /(\.(gz|z|Z)|-gz|-z|_z)$/
|
|
113
|
+
EXTRACT_COMMAND = 'gzip -d -c "%I" > "%O"'
|
|
114
|
+
end # class Gz
|
|
115
|
+
|
|
116
|
+
class Bz2 < Generic
|
|
117
|
+
include Extractable
|
|
118
|
+
include Concrete
|
|
119
|
+
EXTENSION = /\.(bz2|bz)$/
|
|
120
|
+
EXTRACT_COMMAND = 'bzip2 -d -c "%I" > "%O"'
|
|
121
|
+
end # class Bz2
|
|
122
|
+
|
|
123
|
+
class Zip < Generic
|
|
124
|
+
include Extractable
|
|
125
|
+
include Concrete
|
|
126
|
+
EXTENSION = /\.zip$/
|
|
127
|
+
EXTRACT_COMMAND = 'unzip -p "%I" > "%O"'
|
|
128
|
+
end # class Zip
|
|
129
|
+
|
|
130
|
+
module ExtractableDir
|
|
131
|
+
|
|
132
|
+
def self.included ( aClass )
|
|
133
|
+
|
|
134
|
+
aClass.module_eval do
|
|
135
|
+
|
|
136
|
+
include Extractable
|
|
137
|
+
|
|
138
|
+
alias :mk_cmd_extractable :mk_cmd
|
|
139
|
+
|
|
140
|
+
def mk_cmd
|
|
141
|
+
cmd = mk_cmd_extractable
|
|
142
|
+
@tmp.mkpath
|
|
143
|
+
@log = TempPath.new
|
|
144
|
+
cmd.gsub!(/%L/, @log.to_s)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
alias :extract_extractable :extract
|
|
148
|
+
|
|
149
|
+
def extract
|
|
150
|
+
dir = extract_extractable
|
|
151
|
+
# We want the longest common path
|
|
152
|
+
longest = nil
|
|
153
|
+
@log.each_line do |line|
|
|
154
|
+
path = line.split(/\//)
|
|
155
|
+
longest = path if longest.nil?
|
|
156
|
+
longest &= path
|
|
157
|
+
raise CorruptedTarball, self if longest.empty?
|
|
158
|
+
end
|
|
159
|
+
dir.path + longest.join('/')
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
end # module ExtractableDir
|
|
167
|
+
|
|
168
|
+
class Tar < Generic
|
|
169
|
+
include ExtractableDir
|
|
170
|
+
include Concrete
|
|
171
|
+
EXTENSION = /\.tar$/
|
|
172
|
+
EXTRACT_COMMAND = 'tar xvf "%I" -C "%O" > "%L"'
|
|
173
|
+
end # class Tar
|
|
174
|
+
|
|
175
|
+
class TarGz < Generic
|
|
176
|
+
include ExtractableDir
|
|
177
|
+
include Concrete
|
|
178
|
+
EXTENSION = /\.(tar\.gz|tgz)$/
|
|
179
|
+
EXTRACT_COMMAND = 'tar xvzf "%I" -C "%O" > %L'
|
|
180
|
+
end # class TarGz
|
|
181
|
+
|
|
182
|
+
class TarBz2 < Generic
|
|
183
|
+
include ExtractableDir
|
|
184
|
+
include Concrete
|
|
185
|
+
EXTENSION = /\.(tar\.bz2|tbz2|tbz)$/
|
|
186
|
+
EXTRACT_COMMAND = 'bzip2 -c -d %I | tar xvf - -C "%O" > "%L"'
|
|
187
|
+
end # class TarBz2
|
|
188
|
+
|
|
189
|
+
class Directory < Generic
|
|
190
|
+
include Concrete
|
|
191
|
+
|
|
192
|
+
EXTENSION = /()$/
|
|
193
|
+
|
|
194
|
+
def self.match_type ( path, max, best )
|
|
195
|
+
if File.directory? path
|
|
196
|
+
return [path.to_s.size, self]
|
|
197
|
+
end
|
|
198
|
+
return [max, best]
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
end # class Directory
|
|
202
|
+
|
|
203
|
+
def self.guess_class ( path )
|
|
204
|
+
lazy_init
|
|
205
|
+
max = -1
|
|
206
|
+
best = Unknown
|
|
207
|
+
@@subclasses.each do |klass|
|
|
208
|
+
max, best = klass.match_type(path, max, best)
|
|
209
|
+
end
|
|
210
|
+
return best
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def self.guess ( path )
|
|
214
|
+
guess_class(path).new(path)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def self.lazy_init
|
|
218
|
+
return if defined? @@init
|
|
219
|
+
@@init = true
|
|
220
|
+
@@subclasses.delete_if do |klass|
|
|
221
|
+
klass.abstract? or not (klass.is_a? Class) # and constants.include? klass)
|
|
222
|
+
end
|
|
223
|
+
@@subclasses.each do |klass|
|
|
224
|
+
ext = klass.extension
|
|
225
|
+
raise ArgumentError, "Bad extension #{ext}" unless ext.is_a? Regexp
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
end # module FileType
|