whistle 0.1
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/History.txt +3 -0
- data/README.txt +38 -0
- data/bin/whistle +90 -0
- data/lib/config.rb +19 -0
- data/lib/phash.rb +16 -0
- data/lib/relay.rb +24 -0
- data/lib/resource.rb +113 -0
- data/lib/ssl_patch.rb +15 -0
- data/lib/switchbox.rb +54 -0
- data/lib/time_ext.rb +30 -0
- data/lib/version.rb +3 -0
- data/sample/config.yml +12 -0
- data/vendor/rscm-0.5.1-patched-stripped/README +218 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm.rb +14 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/abstract_log_parser.rb +35 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/base.rb +289 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/command_line.rb +146 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/difftool.rb +44 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/line_editor.rb +46 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/mockit.rb +157 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/parser.rb +39 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/path_converter.rb +60 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/platform.rb +26 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revision.rb +103 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revision_file.rb +85 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revision_poller.rb +93 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revisions.rb +79 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/clearcase.rb +182 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/cvs.rb +374 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/cvs_log_parser.rb +154 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/darcs.rb +120 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/darcs_log_parser.rb +65 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/monotone.rb +338 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/monotone_log_parser.rb +109 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/mooky.rb +6 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/perforce.rb +216 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/star_team.rb +104 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/subversion.rb +397 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/subversion_log_parser.rb +165 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/tempdir.rb +17 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/time_ext.rb +11 -0
- data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/version.rb +13 -0
- data/vendor/ruby-feedparser-0.5-stripped/README +14 -0
- data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser.rb +28 -0
- data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/feedparser.rb +300 -0
- data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/filesizes.rb +12 -0
- data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/html-output.rb +126 -0
- data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/html2text-parser.rb +409 -0
- data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/rexml_patch.rb +28 -0
- data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/sgml-parser.rb +332 -0
- data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/text-output.rb +83 -0
- data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/textconverters.rb +120 -0
- metadata +132 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rscm/tempdir'
|
2
|
+
require 'rscm/path_converter'
|
3
|
+
require 'rscm/difftool'
|
4
|
+
|
5
|
+
module RSCM
|
6
|
+
module Difftool
|
7
|
+
# assertion method that reports differences as diff.
|
8
|
+
# useful when comparing big strings
|
9
|
+
def assert_equal_with_diff(expected, actual, message="", temp_basedir=File.dirname(__FILE__) + "/../../target")
|
10
|
+
diff(expected, actual, temp_basedir) do |diff_io, cmd|
|
11
|
+
diff_string = diff_io.read
|
12
|
+
if(diff_string.strip != "")
|
13
|
+
flunk "#{message}\nThere were differences\ndiff command: #{cmd}\ndiff:\n#{diff_string}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
module_function :assert_equal_with_diff
|
18
|
+
|
19
|
+
def diff(expected, actual, temp_basedir, &block)
|
20
|
+
dir = RSCM.new_temp_dir("diff", temp_basedir)
|
21
|
+
|
22
|
+
expected_file = nil
|
23
|
+
if(File.exist?(expected))
|
24
|
+
expected_file = expected
|
25
|
+
else
|
26
|
+
expected_file = "#{dir}/expected"
|
27
|
+
File.open(expected_file, "w") {|io| io.write(expected)}
|
28
|
+
end
|
29
|
+
|
30
|
+
actual_file = "#{dir}/actual"
|
31
|
+
File.open(actual_file, "w") {|io| io.write(actual)}
|
32
|
+
|
33
|
+
difftool = WINDOWS ? File.dirname(__FILE__) + "/../../bin/diff.exe" : "diff"
|
34
|
+
e = RSCM::PathConverter.filepath_to_nativepath(expected_file, false)
|
35
|
+
a = RSCM::PathConverter.filepath_to_nativepath(actual_file, false)
|
36
|
+
cmd = "#{difftool} --ignore-space-change #{e} #{a}"
|
37
|
+
IO.popen(cmd) do |io|
|
38
|
+
yield io, cmd
|
39
|
+
end
|
40
|
+
end
|
41
|
+
module_function :diff
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'ftools'
|
3
|
+
|
4
|
+
module RSCM
|
5
|
+
module LineEditor
|
6
|
+
# Comments out line by line if they match the line_regex.
|
7
|
+
# Does not comment out already commented out lines.
|
8
|
+
# If comment_template is nil, the matching lines will be deleted
|
9
|
+
# Returns true if at least one line is commented out or changed
|
10
|
+
def comment_out(original, line_regex, comment_template, output)
|
11
|
+
did_comment_out = false
|
12
|
+
already_commented_exp = /^[#{comment_template}]/ unless comment_template.nil?
|
13
|
+
original.each_line do |line|
|
14
|
+
out_line = nil
|
15
|
+
if(line_regex =~ line)
|
16
|
+
if(already_commented_exp && already_commented_exp =~ line)
|
17
|
+
out_line = line
|
18
|
+
else
|
19
|
+
did_comment_out = true
|
20
|
+
out_line = "#{comment_template}#{line}" unless comment_template.nil?
|
21
|
+
end
|
22
|
+
else
|
23
|
+
out_line = line
|
24
|
+
end
|
25
|
+
output << out_line unless out_line.nil?
|
26
|
+
end
|
27
|
+
did_comment_out
|
28
|
+
end
|
29
|
+
module_function :comment_out
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class File
|
34
|
+
|
35
|
+
def File.comment_out(path, line_regex, comment_template)
|
36
|
+
temp_file = Tempfile.new(File.basename(path))
|
37
|
+
temp_file_path = temp_file.path
|
38
|
+
original = File.new(path)
|
39
|
+
RSCM::LineEditor.comment_out(original, line_regex, comment_template, temp_file)
|
40
|
+
|
41
|
+
temp_file.close
|
42
|
+
original.close
|
43
|
+
|
44
|
+
File.copy(temp_file_path, path)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'test/unit/assertions'
|
2
|
+
|
3
|
+
module Test #:nodoc:
|
4
|
+
module Unit #:nodoc:
|
5
|
+
class TestCase #:nodoc:
|
6
|
+
def setup_with_mocks
|
7
|
+
@to_verify = []
|
8
|
+
end
|
9
|
+
alias_method :setup, :setup_with_mocks
|
10
|
+
|
11
|
+
def teardown_with_mocks
|
12
|
+
if(@test_passed && @to_verify)
|
13
|
+
@to_verify.each{|m| m.__verify}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
alias_method :teardown, :teardown_with_mocks
|
17
|
+
|
18
|
+
def self.method_added(method)
|
19
|
+
case method.to_s
|
20
|
+
when 'setup'
|
21
|
+
unless method_defined?(:setup_without_mocks)
|
22
|
+
alias_method :setup_without_mocks, :setup
|
23
|
+
define_method(:setup) do
|
24
|
+
setup_with_mocks
|
25
|
+
setup_without_mocks
|
26
|
+
end
|
27
|
+
end
|
28
|
+
when 'teardown'
|
29
|
+
unless method_defined?(:teardown_without_mocks)
|
30
|
+
alias_method :teardown_without_mocks, :teardown
|
31
|
+
define_method(:teardown) do
|
32
|
+
teardown_without_mocks
|
33
|
+
teardown_with_mocks
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def new_mock
|
40
|
+
mock = MockIt::Mock.new
|
41
|
+
@to_verify = [] unless @to_verify
|
42
|
+
@to_verify << mock
|
43
|
+
mock
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module MockIt
|
51
|
+
class Mock
|
52
|
+
include Test::Unit::Assertions
|
53
|
+
|
54
|
+
def initialize
|
55
|
+
@expected_methods=[]
|
56
|
+
@expected_validation_procs=[]
|
57
|
+
@setup_call_procs={}
|
58
|
+
@unexpected_calls = []
|
59
|
+
end
|
60
|
+
|
61
|
+
def __expect(method, &validation_proc)
|
62
|
+
validation_proc=Proc.new {|*args| nil} if validation_proc.nil?
|
63
|
+
@expected_methods<<method
|
64
|
+
@expected_validation_procs<<validation_proc
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def __setup(method, &proc)
|
69
|
+
proc=Proc.new {|*args| nil} if proc.nil?
|
70
|
+
@setup_call_procs[method]=proc
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
def __verify
|
75
|
+
begin
|
76
|
+
assert_no_unexpected_calls
|
77
|
+
assert_all_expected_methods_called
|
78
|
+
ensure
|
79
|
+
initialize
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def method_missing(method, *args, &proc)
|
84
|
+
if(is_expected_call(method))
|
85
|
+
handle_expected_call(method, *args, &proc)
|
86
|
+
elsif(is_setup_call(method))
|
87
|
+
handle_setup_call(method, *args, &proc)
|
88
|
+
else
|
89
|
+
handle_unexpected_call(method)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def respond_to?(method)
|
94
|
+
return super.respond_to?(method) if super.respond_to?(method)
|
95
|
+
method = symbol(method)
|
96
|
+
return true if is_setup_call(method)
|
97
|
+
return true if currently_expected_method == method
|
98
|
+
false
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def symbol(string)
|
104
|
+
return nil if string==""
|
105
|
+
if string.is_a? String then string.intern else string end
|
106
|
+
end
|
107
|
+
|
108
|
+
def assert_no_unexpected_calls
|
109
|
+
assert_equal([], @unexpected_calls, "got unexpected call")
|
110
|
+
end
|
111
|
+
|
112
|
+
def assert_all_expected_methods_called
|
113
|
+
assert(@expected_validation_procs.empty?, "not all expected methods called, calls left: #{@expected_methods.inspect}")
|
114
|
+
end
|
115
|
+
|
116
|
+
def is_expected_call(method)
|
117
|
+
@expected_methods.index(method)
|
118
|
+
end
|
119
|
+
|
120
|
+
def is_setup_call(method)
|
121
|
+
not @setup_call_procs[method].nil?
|
122
|
+
end
|
123
|
+
|
124
|
+
def handle_setup_call(method, *args, &proc)
|
125
|
+
@setup_call_procs[method].call(*args, &proc)
|
126
|
+
end
|
127
|
+
|
128
|
+
def handle_expected_call(method, *args, &proc)
|
129
|
+
assert_equal(currently_expected_method, method, "got unexpected call")
|
130
|
+
validation_proc = current_validation_proc
|
131
|
+
next_call
|
132
|
+
validation_proc.call(*args, &proc)
|
133
|
+
end
|
134
|
+
|
135
|
+
def handle_unexpected_call(method)
|
136
|
+
@unexpected_calls << method
|
137
|
+
flunk("Unexpected method invocation: #{method}")
|
138
|
+
end
|
139
|
+
|
140
|
+
def currently_expected_method
|
141
|
+
if @expected_methods.empty? then nil
|
142
|
+
else @expected_methods[0] end
|
143
|
+
end
|
144
|
+
|
145
|
+
def current_validation_proc
|
146
|
+
if @expected_validation_procs.empty? then nil
|
147
|
+
else @expected_validation_procs[0] end
|
148
|
+
end
|
149
|
+
|
150
|
+
def next_call
|
151
|
+
@expected_methods.delete_at(0)
|
152
|
+
@expected_validation_procs.delete_at(0)
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module RSCM
|
2
|
+
class Parser
|
3
|
+
|
4
|
+
def initialize(break_regexp)
|
5
|
+
@break_regexp = break_regexp
|
6
|
+
end
|
7
|
+
|
8
|
+
def parse(io, skip_line_parsing=false, &line_proc)
|
9
|
+
parse_until_regexp_matches(io, skip_line_parsing, &line_proc)
|
10
|
+
if(skip_line_parsing)
|
11
|
+
nil
|
12
|
+
else
|
13
|
+
next_result
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def parse_line(line)
|
20
|
+
raise "Must override parse_line(line)"
|
21
|
+
end
|
22
|
+
|
23
|
+
def next_result
|
24
|
+
raise "Must override next_result(line)"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def parse_until_regexp_matches(io, skip_line_parsing, &line_proc)
|
30
|
+
io.each_line { |line|
|
31
|
+
yield line if block_given?
|
32
|
+
if line =~ @break_regexp
|
33
|
+
return
|
34
|
+
end
|
35
|
+
parse_line(line) unless skip_line_parsing
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
WIN32 = RUBY_PLATFORM == "i386-mswin32"
|
2
|
+
CYGWIN = RUBY_PLATFORM == "i386-cygwin"
|
3
|
+
WINDOWS = WIN32 || CYGWIN
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
# Utility for converting between win32 and cygwin paths. Does nothing on *nix.
|
8
|
+
module RSCM
|
9
|
+
module PathConverter
|
10
|
+
def filepath_to_nativepath(path, escaped)
|
11
|
+
return nil if path.nil?
|
12
|
+
path = File.expand_path(path)
|
13
|
+
if(WIN32)
|
14
|
+
escaped ? path.gsub(/\//, "\\\\\\\\") : path.gsub(/\//, "\\")
|
15
|
+
elsif(CYGWIN)
|
16
|
+
cygpath = `cygpath --windows #{path}`.chomp
|
17
|
+
escaped ? cygpath.gsub(/\\/, "\\\\\\\\") : cygpath
|
18
|
+
else
|
19
|
+
path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
module_function :filepath_to_nativepath
|
23
|
+
|
24
|
+
def filepath_to_nativeurl(path)
|
25
|
+
return nil if path.nil?
|
26
|
+
if(WINDOWS)
|
27
|
+
urlpath = filepath_to_nativepath(path, false).gsub(/\\/, "/")
|
28
|
+
"file:///#{urlpath}"
|
29
|
+
else
|
30
|
+
"file://#{File.expand_path(path)}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
module_function :filepath_to_nativeurl
|
34
|
+
|
35
|
+
def nativepath_to_filepath(path)
|
36
|
+
return nil if path.nil?
|
37
|
+
path = File.expand_path(path)
|
38
|
+
if(WIN32)
|
39
|
+
path.gsub(/\//, "\\")
|
40
|
+
elsif(CYGWIN)
|
41
|
+
path = path.gsub(/\\/, "/")
|
42
|
+
`cygpath --unix #{path}`.chomp
|
43
|
+
else
|
44
|
+
path
|
45
|
+
end
|
46
|
+
end
|
47
|
+
module_function :nativepath_to_filepath
|
48
|
+
|
49
|
+
def ensure_trailing_slash(url)
|
50
|
+
return nil if url.nil?
|
51
|
+
if(url && url[-1..-1] != "/")
|
52
|
+
"#{url}/"
|
53
|
+
else
|
54
|
+
url
|
55
|
+
end
|
56
|
+
end
|
57
|
+
module_function :ensure_trailing_slash
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
module RSCM
|
4
|
+
module Platform
|
5
|
+
def family
|
6
|
+
target_os = Config::CONFIG["target_os"] or ""
|
7
|
+
return "powerpc-darwin" if target_os.downcase =~ /darwin/
|
8
|
+
return "mswin32" if target_os.downcase =~ /32/
|
9
|
+
return "cygwin" if target_os.downcase =~ /cyg/
|
10
|
+
return "freebsd" if target_os.downcase =~ /freebsd/
|
11
|
+
return "freebsd" if target_os.downcase =~ /linux/
|
12
|
+
return "unknown"
|
13
|
+
end
|
14
|
+
module_function :family
|
15
|
+
|
16
|
+
def user
|
17
|
+
family == "mswin32" ? ENV['USERNAME'] : ENV['USER']
|
18
|
+
end
|
19
|
+
module_function :user
|
20
|
+
|
21
|
+
def prompt(dir=Dir.pwd)
|
22
|
+
prompt = "#{dir.gsub(/\//, File::SEPARATOR)} #{user}$"
|
23
|
+
end
|
24
|
+
module_function :prompt
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'rscm/time_ext'
|
2
|
+
require 'rscm/revision_file'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module RSCM
|
6
|
+
# Represents a collection of RevisionFile that were committed at the
|
7
|
+
# same time, or "more or less at the same time" for non-atomic
|
8
|
+
# SCMs (such as CVS and StarTeam). See Revisions for how to emulate
|
9
|
+
# atomicity for non-atomic SCMs.
|
10
|
+
class Revision
|
11
|
+
include Enumerable
|
12
|
+
|
13
|
+
attr_writer :identifier
|
14
|
+
attr_accessor :developer
|
15
|
+
attr_accessor :message
|
16
|
+
|
17
|
+
def initialize(identifier=nil, time=nil)
|
18
|
+
@identifier = identifier
|
19
|
+
@time = time
|
20
|
+
@files = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def add(file)
|
24
|
+
raise "Can't add #{file} to this revision" unless accept? file
|
25
|
+
@files << file
|
26
|
+
self.developer = file.developer if file.developer
|
27
|
+
self.message = file.message if file.message
|
28
|
+
end
|
29
|
+
|
30
|
+
def identifier(min_or_max = :max)
|
31
|
+
@identifier || time(min_or_max)
|
32
|
+
end
|
33
|
+
|
34
|
+
# The time of this revision. Depending on the value of +min_or_max+,
|
35
|
+
# (should be :min or :max), returns the min or max time of this
|
36
|
+
# revision. (min or max only matters for non-transactional scms)
|
37
|
+
def time(min_or_max = :max)
|
38
|
+
@time || self.collect{|file| file.time}.__send__(min_or_max)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Sets the time for this revision. Should only be used by atomic SCMs.
|
42
|
+
# Non-atomic SCMs should <b>not</b> invoke this method, but instead create
|
43
|
+
# revisions by adding RscmFile objects to a Revisions object.
|
44
|
+
def time=(t)
|
45
|
+
raise "time must be a Time object - it was a #{t.class.name} with the string value #{t}" unless t.is_a?(Time)
|
46
|
+
raise "can't set time to an inferiour value than the previous value" if @time && (t < @time)
|
47
|
+
@time = t
|
48
|
+
end
|
49
|
+
|
50
|
+
# Whether +file+ can be added to this instance.
|
51
|
+
def accept?(file) #:nodoc:
|
52
|
+
return true if empty? || @time
|
53
|
+
|
54
|
+
close_enough_to_min = (time(:min) - file.time).abs <= 60
|
55
|
+
close_enough_to_max = (time(:max) - file.time).abs <= 60
|
56
|
+
close_enough = close_enough_to_min or close_enough_to_max
|
57
|
+
|
58
|
+
close_enough and
|
59
|
+
self.developer == file.developer and
|
60
|
+
self.message == file.message
|
61
|
+
end
|
62
|
+
|
63
|
+
def ==(other)
|
64
|
+
self.to_s == other.to_s
|
65
|
+
end
|
66
|
+
|
67
|
+
# String representation that can be used for debugging.
|
68
|
+
def to_s
|
69
|
+
if(@to_s.nil?)
|
70
|
+
min = time(:min)
|
71
|
+
max = time(:max)
|
72
|
+
t = (min==max) ? min : "#{min}-#{max}"
|
73
|
+
@to_s = "#{identifier} | #{developer} | #{t} | #{message}\n"
|
74
|
+
self.each do |file|
|
75
|
+
@to_s << " " << file.to_s << "\n"
|
76
|
+
end
|
77
|
+
@to_s
|
78
|
+
end
|
79
|
+
@to_s
|
80
|
+
end
|
81
|
+
|
82
|
+
def each(&block)
|
83
|
+
@files.each(&block)
|
84
|
+
end
|
85
|
+
|
86
|
+
def [](n)
|
87
|
+
@files[n]
|
88
|
+
end
|
89
|
+
|
90
|
+
def length
|
91
|
+
@files.length
|
92
|
+
end
|
93
|
+
|
94
|
+
def pop
|
95
|
+
@files.pop
|
96
|
+
end
|
97
|
+
|
98
|
+
def empty?
|
99
|
+
@files.empty?
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|