net-ftp-list 0.3 → 0.4
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/README.txt +1 -7
- data/Rakefile +1 -1
- data/lib/net/ftp/list.rb +22 -27
- data/lib/net/ftp/list/parser.rb +22 -32
- data/lib/net/ftp/list/unix.rb +4 -4
- data/test/test_net_ftp_list.rb +3 -3
- metadata +2 -2
data/README.txt
CHANGED
@@ -21,20 +21,14 @@ See the RFC for more guff on LIST and NLST: http://www.ietf.org/rfc/rfc0959.txt
|
|
21
21
|
* The factory and abstract base class for parsers are one and the same. OO geeks will cry.
|
22
22
|
* More OS's and server types. Only servers that return Unix like LIST responses will work at the moment.
|
23
23
|
* Calling <tt>if entry.file? or entry.dir?</tt> is hard work when you really mean <tt>unless entry.unknown?</tt>
|
24
|
-
* I'm not sure about overwriting Net::FTP's +list+, +ls+ and +dir+. It's a base lib after all and people will be
|
25
|
-
expecting String. Perhaps I'd be better to <tt>class Parser < String</tt> for the abstract parser.
|
26
|
-
* The block handling for +list+, +ls+ and +dir+ has a nasty +map+ that's essentially building up an unused Array.
|
27
24
|
|
28
25
|
== SYNOPSIS
|
29
26
|
|
30
|
-
By requiring Net::FTP::List instances are created by calling any of Net::FTP's <tt>list</tt>, <tt>ls</tt> or
|
31
|
-
<tt>dir</tt> metods. The <tt>to_s</tt> method still returns the raw line so for the most part this should be
|
32
|
-
transparent.
|
33
|
-
|
34
27
|
require 'net/ftp' # Not really required but I like to list dependencies sometimes.
|
35
28
|
require 'net/ftp/list'
|
36
29
|
|
37
30
|
ftp = Net::FTP.open('somehost.com', 'user', 'pass')
|
31
|
+
ftp.extend Net::FTP::List # Tweak list, ls and dir to returned parsed content.
|
38
32
|
ftp.list('/some/path') do |entry|
|
39
33
|
# Ignore everything that's not a file (so symlinks, directories and devices etc.)
|
40
34
|
next unless entry.file?
|
data/Rakefile
CHANGED
data/lib/net/ftp/list.rb
CHANGED
@@ -8,30 +8,18 @@ require 'net/ftp/list/unix'
|
|
8
8
|
module Net #:nodoc:
|
9
9
|
class FTP #:nodoc:
|
10
10
|
|
11
|
-
alias_method :raw_list, :list
|
12
|
-
def list(*args, &block)
|
13
|
-
# TODO: Map in void context when you pass a block.
|
14
|
-
raw_list(*args).map do |raw|
|
15
|
-
entry = Net::FTP::List.parse(raw)
|
16
|
-
block ? yield(entry) : entry
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
11
|
# Parse FTP LIST responses.
|
21
12
|
#
|
22
|
-
#
|
23
|
-
#
|
13
|
+
# Mixin the +Net::FTP::List+ module and subsequent calls to the Net::FTP +list+, +ls+ or +dir+ methods will be
|
14
|
+
# parsed by the LIST parser as best it can.
|
24
15
|
#
|
25
16
|
# == Creation
|
26
17
|
#
|
27
|
-
# By requiring Net::FTP::List instances are created by calling any of Net::FTP's +list+, +ls+ or
|
28
|
-
# +dir+ metods. The +to_s+ method still returns the raw line so for the most part this should be
|
29
|
-
# transparent.
|
30
|
-
#
|
31
18
|
# require 'net/ftp' # Not really required but I like to list dependencies sometimes.
|
32
19
|
# require 'net/ftp/list'
|
33
20
|
#
|
34
21
|
# ftp = Net::FTP.open('somehost.com', 'user', 'pass')
|
22
|
+
# ftp.extend Net::FTP::List
|
35
23
|
# ftp.list('/some/path') do |entry|
|
36
24
|
# # Ignore everything that's not a file (so symlinks, directories and devices etc.)
|
37
25
|
# next unless entry.file?
|
@@ -46,22 +34,29 @@ module Net #:nodoc:
|
|
46
34
|
# None at this time. At worst you'll end up with an Net::FTP::List::Unknown instance which won't have any extra
|
47
35
|
# useful information. Methods like <tt>dir?</tt>, <tt>file?</tt> and <tt>symlink?</tt> will all return +false+.
|
48
36
|
module List
|
49
|
-
class << self
|
50
37
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
38
|
+
def self.extended(klass) #:nodoc:
|
39
|
+
class << klass
|
40
|
+
|
41
|
+
alias_method :raw_list, :list
|
42
|
+
def list(*args, &block)
|
43
|
+
if block
|
44
|
+
raw_list(*args) do |raw|
|
45
|
+
Net::FTP::List::Parser.parse(raw)
|
46
|
+
yield raw
|
47
|
+
end
|
48
|
+
else
|
49
|
+
raw_list(*args).map do |raw|
|
50
|
+
Net::FTP::List::Parser.parse(raw)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
62
54
|
|
55
|
+
end
|
63
56
|
end
|
57
|
+
|
64
58
|
end
|
65
59
|
|
66
60
|
end
|
67
61
|
end
|
62
|
+
|
data/lib/net/ftp/list/parser.rb
CHANGED
@@ -21,55 +21,54 @@ module Net
|
|
21
21
|
class Parser
|
22
22
|
@@parsers = []
|
23
23
|
|
24
|
+
# Parse a raw FTP LIST line.
|
25
|
+
#
|
26
|
+
# By default just takes and set the raw list entry.
|
27
|
+
#
|
28
|
+
# Net::FTP::List.parse(raw_list_string) # => Net::FTP::List::Parser instance.
|
29
|
+
def initialize(raw)
|
30
|
+
@raw = raw
|
31
|
+
end
|
32
|
+
|
24
33
|
# The raw list entry string.
|
25
|
-
|
34
|
+
def raw
|
35
|
+
@raw
|
36
|
+
end
|
37
|
+
alias_method :to_s, :raw
|
26
38
|
|
27
39
|
# The items basename (filename).
|
28
|
-
|
40
|
+
def basename
|
41
|
+
@basename
|
42
|
+
end
|
29
43
|
|
30
44
|
# Looks like a directory, try CWD.
|
31
45
|
def dir?
|
32
|
-
|
46
|
+
!!@dir
|
33
47
|
end
|
34
48
|
|
35
49
|
# Looks like a file, try RETR.
|
36
50
|
def file?
|
37
|
-
|
51
|
+
!!@file
|
38
52
|
end
|
39
53
|
|
40
54
|
# Looks like a symbolic link.
|
41
55
|
def symlink?
|
42
|
-
|
56
|
+
!!@symlink
|
43
57
|
end
|
44
58
|
|
45
|
-
# Parse a raw FTP LIST line.
|
46
|
-
#
|
47
|
-
# By default just takes and set the raw list entry.
|
48
|
-
#
|
49
|
-
# Net::FTP::List.parse(raw_list_string) # => Net::FTP::List::Parser instance.
|
50
|
-
def initialize(raw)
|
51
|
-
self.raw = raw
|
52
|
-
end
|
53
|
-
|
54
|
-
# Stringify.
|
55
|
-
def to_s
|
56
|
-
raw
|
57
|
-
end
|
58
|
-
alias_method :raw, :to_s
|
59
|
-
|
60
59
|
class << self
|
61
|
-
|
62
60
|
# Acts as a factory.
|
63
61
|
#
|
64
62
|
# TODO: Having a class be both factory and abstract implementation seems a little nutty to me. If it ends up
|
65
63
|
# too confusing or gives anyone the shits I'll move it.
|
66
|
-
def inherited(klass)
|
64
|
+
def inherited(klass) #:nodoc:
|
67
65
|
@@parsers << klass
|
68
66
|
end
|
69
67
|
|
70
68
|
# Factory method.
|
71
69
|
#
|
72
|
-
# Attempt to find and parse a list item
|
70
|
+
# Attempt to find a parser and parse a list item. At worst the item will return an Net::FTP::List::Unknown
|
71
|
+
# instance. This may change in the future so that only parsable entries are kept.
|
73
72
|
def parse(raw)
|
74
73
|
@@parsers.reverse.each do |parser|
|
75
74
|
begin
|
@@ -81,15 +80,6 @@ module Net
|
|
81
80
|
end
|
82
81
|
end
|
83
82
|
|
84
|
-
protected
|
85
|
-
# Protected boolean.
|
86
|
-
attr_accessor :file, :dir, :symlink
|
87
|
-
|
88
|
-
# Protected raw list entry string.
|
89
|
-
attr_writer :raw
|
90
|
-
|
91
|
-
# Protected item basename (filename).
|
92
|
-
attr_writer :basename
|
93
83
|
end
|
94
84
|
|
95
85
|
# Unknown parser.
|
data/lib/net/ftp/list/unix.rb
CHANGED
@@ -38,16 +38,16 @@ module Net
|
|
38
38
|
match = REGEXP.match(raw.strip) or raise ParserError
|
39
39
|
|
40
40
|
case match[1]
|
41
|
-
when /d/ then
|
42
|
-
when /l/ then
|
43
|
-
when /[f-]/ then
|
41
|
+
when /d/ then @dir = true
|
42
|
+
when /l/ then @symlink = true
|
43
|
+
when /[f-]/ then @file = true
|
44
44
|
when /[bc]/ then # Do nothing with devices for now.
|
45
45
|
else ParserError 'Unknown LIST entry type.'
|
46
46
|
end
|
47
47
|
|
48
48
|
# TODO: Permissions, users, groups, date/time.
|
49
49
|
|
50
|
-
|
50
|
+
@basename = match[21].match(/^(.+)(?:\s+\->.+)?$/)[0].strip
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
data/test/test_net_ftp_list.rb
CHANGED
@@ -4,8 +4,8 @@ require 'net/ftp/list'
|
|
4
4
|
class TestNetFTPList < Test::Unit::TestCase
|
5
5
|
|
6
6
|
def setup
|
7
|
-
@dir = Net::FTP::List.
|
8
|
-
@file = Net::FTP::List.
|
7
|
+
@dir = Net::FTP::List::Parser.parse('drwxr-xr-x 4 user group 4096 Dec 10 20:23 etc')
|
8
|
+
@file = Net::FTP::List::Parser.parse('-rw-r--r-- 1 root other 531 Jan 29 03:26 README')
|
9
9
|
end
|
10
10
|
|
11
11
|
def test_parse_new
|
@@ -14,7 +14,7 @@ class TestNetFTPList < Test::Unit::TestCase
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def test_rubbish_lines
|
17
|
-
assert_instance_of Net::FTP::List::Unknown, Net::FTP::List.
|
17
|
+
assert_instance_of Net::FTP::List::Unknown, Net::FTP::List::Parser.parse("++ bah! ++")
|
18
18
|
end
|
19
19
|
|
20
20
|
def test_ruby_unix_like_dir
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: net-ftp-list
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "0.
|
7
|
-
date: 2008-01-
|
6
|
+
version: "0.4"
|
7
|
+
date: 2008-01-16 00:00:00 +11:00
|
8
8
|
summary: Parse FTP LIST command output.
|
9
9
|
require_paths:
|
10
10
|
- lib
|