bfs-ftp 0.4.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 996793546b6def5f901a9d609a1a87fb4c229ce11808519119b0b3e485d459eb
4
+ data.tar.gz: 973ca56c2d859de7ca93fb6774055667b66f929cbcc857849e24b1f6f0cb0723
5
+ SHA512:
6
+ metadata.gz: cd8dd65cf5f0b0230a0f30e2f51fc4f2d438768df108a7d9d0c07f0a129fe6fb2aded68c2ef8310cd37d8767ec36c9270f97618932044e4bd237174262d82135
7
+ data.tar.gz: 36ab986b28ca63d6c39f3d0bb32805509a0b66f332e153c168b5e8c0f682d0475f00e97c2a56b7cf3dd517323bdc232c045d7e31d7105b9cf84d452a68dead9a
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'bfs-ftp'
3
+ s.version = File.read(File.expand_path('../.version', __dir__)).strip
4
+ s.platform = Gem::Platform::RUBY
5
+
6
+ s.licenses = ['Apache-2.0']
7
+ s.summary = 'FTP adapter for bfs'
8
+ s.description = 'https://github.com/bsm/bfs.rb'
9
+
10
+ s.authors = ['Dimitrij Denissenko']
11
+ s.email = 'dimitrij@blacksquaremedia.com'
12
+ s.homepage = 'https://github.com/bsm/bfs.rb'
13
+
14
+ s.executables = []
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- spec/*`.split("\n")
17
+ s.require_paths = ['lib']
18
+ s.required_ruby_version = '>= 2.4.0'
19
+
20
+ s.add_dependency 'bfs', s.version
21
+ s.add_dependency 'net-ftp-list'
22
+ end
@@ -0,0 +1,136 @@
1
+ require 'bfs'
2
+ require 'net/ftp/list'
3
+ require 'cgi'
4
+
5
+ module BFS
6
+ module Bucket
7
+ # FTP buckets are operating on ftp servers
8
+ class FTP < Abstract
9
+
10
+ # Initializes a new bucket
11
+ # @param [String] host the host name
12
+ # @param [Hash] opts options
13
+ # @option opts [Integer] :port custom port. Default: 21.
14
+ # @option opts [Boolean] :ssl will attempt to use SSL.
15
+ # @option opts [String] :username user name for login.
16
+ # @option opts [String] :password password for login.
17
+ # @option opts [String] :passive connect in passive mode. Default: true.
18
+ # @option opts [String] :prefix optional prefix.
19
+ def initialize(host, opts={})
20
+ opts = opts.dup
21
+ opts.keys.each do |key|
22
+ val = opts.delete(key)
23
+ opts[key.to_sym] = val unless val.nil?
24
+ end
25
+ super(opts)
26
+
27
+ prefix = opts.delete(:prefix)
28
+ @client = Net::FTP.new(host, opts)
29
+ @client.binary = true
30
+
31
+ if prefix # rubocop:disable Style/GuardClause
32
+ prefix = norm_path(prefix)
33
+ mkdir_p(prefix)
34
+ @client.chdir(prefix)
35
+ end
36
+ end
37
+
38
+ # Lists the contents of a bucket using a glob pattern
39
+ def ls(pattern='**/*', _opts={})
40
+ dir = pattern[%r{^[^\*\?\{\}\[\]]+/}]
41
+ dir&.chomp!('/')
42
+
43
+ Enumerator.new do |y|
44
+ glob(dir) do |path|
45
+ y << path if File.fnmatch?(pattern, path, File::FNM_PATHNAME)
46
+ end
47
+ end
48
+ end
49
+
50
+ # Info returns the object info
51
+ def info(path, _opts={})
52
+ path = norm_path(path)
53
+ BFS::FileInfo.new(path, @client.size(path), @client.mtime(path))
54
+ rescue Net::FTPPermError
55
+ raise BFS::FileNotFound, path
56
+ end
57
+
58
+ # Creates a new file and opens it for writing
59
+ def create(path, opts={}, &block)
60
+ path = norm_path(path)
61
+ enc = opts.delete(:encoding) || @encoding
62
+ temp = BFS::TempWriter.new(path, encoding: enc) do |t|
63
+ mkdir_p File.dirname(path)
64
+ @client.put(t, path)
65
+ end
66
+ return temp unless block
67
+
68
+ begin
69
+ yield temp
70
+ ensure
71
+ temp.close
72
+ end
73
+ end
74
+
75
+ # Opens an existing file for reading
76
+ def open(path, opts={}, &block)
77
+ path = norm_path(path)
78
+ enc = opts.delete(:encoding) || @encoding
79
+ temp = Tempfile.new(File.basename(path), encoding: enc)
80
+ temp.close
81
+
82
+ @client.get(path, temp.path)
83
+ File.open(temp.path, encoding: enc, &block)
84
+ rescue Net::FTPPermError
85
+ raise BFS::FileNotFound, path
86
+ end
87
+
88
+ # Deletes a file.
89
+ def rm(path, _opts={})
90
+ path = norm_path(path)
91
+ @client.delete(path)
92
+ rescue Net::FTPPermError # rubocop:disable Lint/HandleExceptions
93
+ end
94
+
95
+ # Closes the underlying connection
96
+ def close
97
+ @client.close
98
+ end
99
+
100
+ private
101
+
102
+ def glob(dir, &block)
103
+ @client.ls(dir || '.') do |e|
104
+ entry = Net::FTP::List.parse(e)
105
+ if entry.dir?
106
+ subdir = [dir, entry.basename].compact.join('/')
107
+ glob subdir, &block
108
+ elsif entry.file?
109
+ yield [dir, entry.basename].compact.join('/')
110
+ end
111
+ end
112
+ end
113
+
114
+ def mkdir_p(path)
115
+ parts = path.split('/').reject(&:empty?)
116
+ (0...parts.size).each do |i|
117
+ begin
118
+ @client.mkdir parts[0..i].join('/')
119
+ rescue Net::FTPPermError # rubocop:disable Lint/HandleExceptions
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ BFS.register('ftp', 'sftp') do |url|
128
+ params = CGI.parse(url.query.to_s)
129
+
130
+ BFS::Bucket::FTP.new url.host,
131
+ username: url.user ? CGI.unescape(url.user) : nil,
132
+ password: url.password ? CGI.unescape(url.password) : nil,
133
+ port: url.port,
134
+ ssl: params.key?('ssl') || url.scheme == 'sftp',
135
+ prefix: params.key?('prefix') ? params['prefix'].first : nil
136
+ end
@@ -0,0 +1 @@
1
+ require 'bfs/bucket/ftp'
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ sandbox = { host: '127.0.0.1', port: 7021, username: 'ftpuser', password: 'ftppass' }.freeze
4
+ run_spec = \
5
+ begin
6
+ ftp = Net::FTP.new sandbox[:host], sandbox
7
+ ftp.list
8
+ ftp.close
9
+ rescue Errno::ECONNREFUSED, Net::FTPError => e
10
+ warn "WARNING: unable to run #{File.basename __FILE__}: #{e.message}"
11
+ false
12
+ end
13
+
14
+ RSpec.describe BFS::Bucket::FTP, if: run_spec do
15
+ subject { described_class.new sandbox[:host], sandbox.merge(prefix: SecureRandom.uuid) }
16
+ after { subject.close }
17
+
18
+ it_behaves_like 'a bucket',
19
+ content_type: false,
20
+ metadata: false
21
+
22
+ it 'should resolve from URL' do
23
+ bucket = BFS.resolve('ftp://ftpuser:ftppass@127.0.0.1:7021')
24
+ expect(bucket).to be_instance_of(described_class)
25
+ end
26
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bfs-ftp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.1
5
+ platform: ruby
6
+ authors:
7
+ - Dimitrij Denissenko
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-09-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bfs
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.4.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.4.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: net-ftp-list
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: https://github.com/bsm/bfs.rb
42
+ email: dimitrij@blacksquaremedia.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - bfs-ftp.gemspec
48
+ - lib/bfs/bucket/ftp.rb
49
+ - lib/bfs/ftp.rb
50
+ - spec/bfs/bucket/ftp_spec.rb
51
+ homepage: https://github.com/bsm/bfs.rb
52
+ licenses:
53
+ - Apache-2.0
54
+ metadata: {}
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 2.4.0
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubygems_version: 3.0.3
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: FTP adapter for bfs
74
+ test_files:
75
+ - spec/bfs/bucket/ftp_spec.rb