net-ftp-list 3.2.11 → 3.3.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +21 -0
- data/.gitignore +9 -0
- data/.rubocop.yml +17 -0
- data/Gemfile +1 -5
- data/Gemfile.lock +47 -51
- data/Rakefile +10 -42
- data/lib/net/ftp/list.rb +3 -4
- data/lib/net/ftp/list/entry.rb +33 -53
- data/lib/net/ftp/list/microsoft.rb +14 -16
- data/lib/net/ftp/list/netware.rb +8 -10
- data/lib/net/ftp/list/parser.rb +35 -18
- data/lib/net/ftp/list/rumpus.rb +9 -10
- data/lib/net/ftp/list/unix.rb +31 -38
- data/lib/net/ftp/list/unknown.rb +3 -6
- data/net-ftp-list.gemspec +15 -57
- data/test/test_net_ftp_list.rb +2 -3
- data/test/test_net_ftp_list_entry.rb +20 -21
- data/test/test_net_ftp_list_microsoft.rb +6 -7
- data/test/test_net_ftp_list_netware.rb +6 -8
- data/test/test_net_ftp_list_rumpus.rb +5 -6
- data/test/test_net_ftp_list_unix.rb +49 -62
- metadata +46 -12
- data/.ruby-version +0 -1
- data/VERSION.yml +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3664e5c75774117ae0ec40734948526a60d5f8b55a38629a9abe56e0d2599813
|
4
|
+
data.tar.gz: 26ebefa96b9b63150c4c63af7c7912c8346f9ae080066eac3d37a198264645a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cff6489e1af74de5c0c25b5b5461b2be0ce57f4cb52086d36f7876836db07cacd120e3e34143c63d0ea06ad7504092ff1702ff7c87513368468aee72ef2486ad
|
7
|
+
data.tar.gz: 655bee68bff7169c0ab47f6e9124c129e6339b953e635165cb7feebd82fa44a85b921d688b63b432ad0eab8c7c8a189107ab538f5ec4bfdca8df0ec22f1f3ff7
|
@@ -0,0 +1,21 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [main]
|
6
|
+
pull_request:
|
7
|
+
branches: [main]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
ruby:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
strategy:
|
13
|
+
matrix:
|
14
|
+
ruby-version: ["2.5", "2.6", "2.7", "3.0"]
|
15
|
+
steps:
|
16
|
+
- uses: actions/checkout@v2
|
17
|
+
- uses: ruby/setup-ruby@v1
|
18
|
+
with:
|
19
|
+
ruby-version: ${{ matrix.ruby-version }}
|
20
|
+
bundler-cache: true
|
21
|
+
- run: bundle exec rake
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
inherit_gem:
|
2
|
+
rubocop-bsm:
|
3
|
+
- default.yml
|
4
|
+
inherit_mode:
|
5
|
+
merge:
|
6
|
+
- Exclude
|
7
|
+
|
8
|
+
AllCops:
|
9
|
+
TargetRubyVersion: "2.5"
|
10
|
+
|
11
|
+
Metrics/ParameterLists:
|
12
|
+
Exclude:
|
13
|
+
- lib/net/ftp/list/entry.rb
|
14
|
+
Metrics/MethodLength:
|
15
|
+
Exclude:
|
16
|
+
- lib/net/ftp/list/unix.rb
|
17
|
+
- test/**/*.rb
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,63 +1,59 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
net-ftp-list (3.3.0)
|
5
|
+
|
1
6
|
GEM
|
2
7
|
remote: https://rubygems.org/
|
3
8
|
specs:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
oauth2 (1.4.0)
|
40
|
-
faraday (>= 0.8, < 0.13)
|
41
|
-
jwt (~> 1.0)
|
42
|
-
multi_json (~> 1.3)
|
43
|
-
multi_xml (~> 0.5)
|
44
|
-
rack (>= 1.2, < 3)
|
45
|
-
power_assert (1.1.1)
|
46
|
-
psych (3.0.2)
|
47
|
-
rack (2.0.4)
|
48
|
-
rake (12.3.1)
|
49
|
-
rdoc (6.0.3)
|
50
|
-
semver2 (3.4.2)
|
51
|
-
test-unit (3.2.7)
|
9
|
+
ast (2.4.2)
|
10
|
+
parallel (1.20.1)
|
11
|
+
parser (3.0.1.1)
|
12
|
+
ast (~> 2.4.1)
|
13
|
+
power_assert (2.0.0)
|
14
|
+
rainbow (3.0.0)
|
15
|
+
rake (13.0.3)
|
16
|
+
regexp_parser (2.1.1)
|
17
|
+
rexml (3.2.5)
|
18
|
+
rubocop (1.15.0)
|
19
|
+
parallel (~> 1.10)
|
20
|
+
parser (>= 3.0.0.0)
|
21
|
+
rainbow (>= 2.2.2, < 4.0)
|
22
|
+
regexp_parser (>= 1.8, < 3.0)
|
23
|
+
rexml
|
24
|
+
rubocop-ast (>= 1.5.0, < 2.0)
|
25
|
+
ruby-progressbar (~> 1.7)
|
26
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
27
|
+
rubocop-ast (1.6.0)
|
28
|
+
parser (>= 3.0.1.1)
|
29
|
+
rubocop-bsm (0.6.0)
|
30
|
+
rubocop (~> 1.0)
|
31
|
+
rubocop-performance
|
32
|
+
rubocop-rake
|
33
|
+
rubocop-rspec
|
34
|
+
rubocop-performance (1.11.3)
|
35
|
+
rubocop (>= 1.7.0, < 2.0)
|
36
|
+
rubocop-ast (>= 0.4.0)
|
37
|
+
rubocop-rake (0.5.1)
|
38
|
+
rubocop
|
39
|
+
rubocop-rspec (2.3.0)
|
40
|
+
rubocop (~> 1.0)
|
41
|
+
rubocop-ast (>= 1.1.0)
|
42
|
+
ruby-progressbar (1.11.0)
|
43
|
+
test-unit (3.4.1)
|
52
44
|
power_assert
|
53
|
-
|
45
|
+
timecop (0.9.4)
|
46
|
+
unicode-display_width (2.0.0)
|
54
47
|
|
55
48
|
PLATFORMS
|
56
49
|
ruby
|
57
50
|
|
58
51
|
DEPENDENCIES
|
59
|
-
|
52
|
+
net-ftp-list!
|
53
|
+
rake
|
54
|
+
rubocop-bsm
|
60
55
|
test-unit
|
56
|
+
timecop
|
61
57
|
|
62
58
|
BUNDLED WITH
|
63
|
-
|
59
|
+
2.2.14
|
data/Rakefile
CHANGED
@@ -1,54 +1,22 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require 'yaml'
|
4
|
-
|
5
|
-
begin
|
6
|
-
require 'jeweler'
|
7
|
-
Jeweler::Tasks.new do |gem|
|
8
|
-
gem.name = "net-ftp-list"
|
9
|
-
gem.summary = %Q{Parse FTP LIST command output.}
|
10
|
-
gem.email = "enquiries@statelesssystems.com"
|
11
|
-
gem.homepage = "http://github.com/stateless-systems/net-ftp-list"
|
12
|
-
gem.authors = ["Stateless Systems"]
|
13
|
-
end
|
14
|
-
Jeweler::RubygemsDotOrgTasks.new
|
15
|
-
rescue LoadError
|
16
|
-
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
17
|
-
end
|
18
|
-
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'bundler/gem_tasks'
|
19
3
|
require 'rake/testtask'
|
4
|
+
require 'rdoc/task'
|
5
|
+
require 'rubocop/rake_task'
|
6
|
+
|
20
7
|
Rake::TestTask.new(:test) do |test|
|
21
8
|
test.libs << 'lib' << 'test'
|
22
9
|
test.pattern = 'test/**/test_*.rb'
|
23
10
|
test.verbose = true
|
24
11
|
end
|
25
12
|
|
26
|
-
begin
|
27
|
-
require 'rcov/rcovtask'
|
28
|
-
Rcov::RcovTask.new do |test|
|
29
|
-
test.libs << 'test'
|
30
|
-
test.pattern = 'test/**/test_*.rb'
|
31
|
-
test.verbose = true
|
32
|
-
end
|
33
|
-
rescue LoadError
|
34
|
-
task :rcov do
|
35
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
task :default => :test
|
40
|
-
|
41
|
-
require 'rdoc/task'
|
42
13
|
Rake::RDocTask.new do |rdoc|
|
43
|
-
if File.exist?('VERSION.yml')
|
44
|
-
config = YAML.load(File.read('VERSION.yml'))
|
45
|
-
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
46
|
-
else
|
47
|
-
version = ""
|
48
|
-
end
|
49
|
-
|
50
14
|
rdoc.rdoc_dir = 'rdoc'
|
51
|
-
rdoc.title =
|
15
|
+
rdoc.title = 'net-ftp-list'
|
52
16
|
rdoc.rdoc_files.include('README*')
|
53
17
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
18
|
end
|
19
|
+
|
20
|
+
RuboCop::RakeTask.new(:rubocop)
|
21
|
+
|
22
|
+
task default: %i[rubocop test]
|
data/lib/net/ftp/list.rb
CHANGED
@@ -21,9 +21,9 @@ module Net::FTP::List
|
|
21
21
|
end
|
22
22
|
|
23
23
|
# Parse a line from FTP LIST responsesa and return a Net::FTP::List::Entry
|
24
|
-
def self.parse(*args)
|
25
|
-
Parser.
|
26
|
-
entry =
|
24
|
+
def self.parse(*args, **opts)
|
25
|
+
Parser.parsers.each do |parser|
|
26
|
+
entry = parser.parse(*args, **opts)
|
27
27
|
return entry if entry
|
28
28
|
end
|
29
29
|
end
|
@@ -32,4 +32,3 @@ module Net::FTP::List
|
|
32
32
|
class ParseError < RuntimeError
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
data/lib/net/ftp/list/entry.rb
CHANGED
@@ -2,17 +2,28 @@
|
|
2
2
|
class Net::FTP::List::Entry
|
3
3
|
include Comparable
|
4
4
|
|
5
|
-
|
5
|
+
attr_reader :raw, :basename, :type, :filesize, :mtime, :server_type, :symlink_destination
|
6
|
+
alias to_s raw
|
7
|
+
alias name basename
|
8
|
+
alias size filesize
|
6
9
|
|
7
10
|
# Create a new entry object. The additional argument is the list of metadata keys
|
8
11
|
# that can be used on the object. By default just takes and set the raw list entry.
|
9
12
|
# Net::FTP::List.parse(raw_list_string) # => Net::FTP::List::Parser instance.
|
10
|
-
def initialize(raw_ls_line,
|
13
|
+
def initialize(raw_ls_line,
|
14
|
+
basename: nil,
|
15
|
+
type: nil,
|
16
|
+
mtime: nil,
|
17
|
+
filesize: nil,
|
18
|
+
server_type: nil,
|
19
|
+
symlink_destination: nil) #:nodoc:
|
11
20
|
@raw = raw_ls_line.respond_to?(:force_encoding) ? raw_ls_line.force_encoding('utf-8') : raw_ls_line
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
21
|
+
@basename = basename || ''
|
22
|
+
@type = type
|
23
|
+
@mtime = mtime || Time.now
|
24
|
+
@filesize = filesize || 0
|
25
|
+
@server_type = server_type || 'Unknown'
|
26
|
+
@symlink_destination = symlink_destination
|
16
27
|
end
|
17
28
|
|
18
29
|
# Tests for objects equality (value and type).
|
@@ -22,83 +33,52 @@ class Net::FTP::List::Entry
|
|
22
33
|
# @return [true, false] true if the objects are equal and have the same type; false otherwise.
|
23
34
|
#
|
24
35
|
def eql?(other)
|
25
|
-
return false
|
26
|
-
return true if
|
36
|
+
return false unless other.is_a?(::Net::FTP::List::Entry)
|
37
|
+
return true if equal?(other)
|
27
38
|
|
28
|
-
|
39
|
+
raw == other.raw # if it's exactly the same line then the objects are the same
|
29
40
|
end
|
30
41
|
|
31
|
-
|
32
42
|
# Compares the receiver against another object.
|
33
43
|
#
|
34
44
|
# @param (see #eql?)
|
35
45
|
#
|
36
|
-
# @return [
|
46
|
+
# @return [Integer] -1, 0, or +1 depending on whether the receiver is less than, equal to, or greater than the other object.
|
37
47
|
#
|
38
48
|
def <=>(other)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
49
|
+
case other
|
50
|
+
when ::Net::FTP::List::Entry
|
51
|
+
return filesize <=> other.filesize
|
52
|
+
when Numeric
|
53
|
+
return filesize <=> other
|
43
54
|
end
|
44
|
-
raise ArgumentError.new('comparison of %s with %s failed!' % [self.class, other.class])
|
45
|
-
end
|
46
55
|
|
47
|
-
|
48
|
-
def raw
|
49
|
-
@raw ||= ''
|
50
|
-
end
|
51
|
-
alias_method :to_s, :raw
|
52
|
-
|
53
|
-
# The items basename (filename).
|
54
|
-
def basename
|
55
|
-
@basename ||= ''
|
56
|
-
end
|
57
|
-
alias name basename
|
58
|
-
|
59
|
-
# Symlink destination, the "/etc" in "bar -> /etc". May be nil.
|
60
|
-
def symlink_destination
|
61
|
-
@symlink_destination
|
56
|
+
raise ArgumentError, format('comparison of %<self>s with %<other>s failed!', self: self.class, other: other.class)
|
62
57
|
end
|
63
58
|
|
64
59
|
# Looks like a directory, try CWD.
|
65
60
|
def dir?
|
66
|
-
|
61
|
+
type == :dir
|
67
62
|
end
|
68
63
|
alias directory? dir?
|
69
64
|
|
70
65
|
# Looks like a file, try RETR.
|
71
66
|
def file?
|
72
|
-
|
67
|
+
type == :file
|
73
68
|
end
|
74
69
|
|
75
70
|
# Looks like a symbolic link.
|
76
71
|
def symlink?
|
77
|
-
|
72
|
+
type == :symlink
|
78
73
|
end
|
79
74
|
|
80
75
|
# Looks like a device.
|
81
76
|
def device?
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
# Returns the modification time of the file/directory or the current time if unknown
|
86
|
-
def mtime
|
87
|
-
@mtime || Time.now
|
88
|
-
end
|
89
|
-
|
90
|
-
# Returns the filesize of the entry or 0 for directorties
|
91
|
-
def filesize
|
92
|
-
@filesize || 0
|
93
|
-
end
|
94
|
-
alias size filesize
|
95
|
-
|
96
|
-
# Returns the detected server type if this entry
|
97
|
-
def server_type
|
98
|
-
@server_type || "Unknown"
|
77
|
+
type == :device
|
99
78
|
end
|
100
79
|
|
80
|
+
# Is the entry type unknown?
|
101
81
|
def unknown?
|
102
|
-
|
82
|
+
!dir? && !file? && !symlink? && !device?
|
103
83
|
end
|
104
84
|
end
|
@@ -11,36 +11,34 @@ require 'date'
|
|
11
11
|
class Net::FTP::List::Microsoft < Net::FTP::List::Parser
|
12
12
|
REGEXP = %r!
|
13
13
|
^\s*
|
14
|
-
([0-9
|
14
|
+
([0-9\-:/]{5,})\s+([0-9\-:]{3,}(?:[aApP][mM])?)\s+
|
15
15
|
(?:(<DIR>)|([0-9]+))\s+
|
16
16
|
(\S.*)
|
17
17
|
\s*$
|
18
|
-
!x
|
18
|
+
!x.freeze
|
19
19
|
|
20
20
|
# Parse a Microsoft(NT) like FTP LIST entries.
|
21
|
-
def self.parse(raw)
|
21
|
+
def self.parse(raw, timezone: :utc)
|
22
22
|
match = REGEXP.match(raw.strip) or return false
|
23
23
|
|
24
|
-
date_match =
|
24
|
+
date_match = /(\d\d).(\d\d).(\d\d(?:\d\d)?)/.match(match[1])
|
25
25
|
date_format = date_match[1].to_i > 12 ? '%d-%m-%y' : '%m-%d-%y'
|
26
|
-
date_format.sub!(
|
26
|
+
date_format.sub!(/%y/, '%Y') if date_match[3].length > 2
|
27
27
|
|
28
|
-
|
29
|
-
date_format.
|
30
|
-
date_format.
|
28
|
+
unless /-/.match?(match[1])
|
29
|
+
date_format.tr!('-', '/') if %r{/}.match?(match[1])
|
30
|
+
date_format.tr!('-', ':') if /:/.match?(match[1])
|
31
31
|
end
|
32
32
|
|
33
|
-
mtime =
|
34
|
-
|
35
|
-
filesize = is_dir ? 0 : match[4].to_i
|
33
|
+
mtime = parse_time("#{match[1]} #{match[2]}", format: "#{date_format} %H:%M%p", timezone: timezone)
|
34
|
+
type = match[3] == '<DIR>' ? :dir : :file
|
36
35
|
|
37
36
|
emit_entry(
|
38
37
|
raw,
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:mtime => mtime
|
38
|
+
type: type,
|
39
|
+
filesize: match[4].to_i,
|
40
|
+
basename: match[5],
|
41
|
+
mtime: mtime,
|
44
42
|
)
|
45
43
|
end
|
46
44
|
end
|