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.
- checksums.yaml +7 -0
- data/bfs-ftp.gemspec +22 -0
- data/lib/bfs/bucket/ftp.rb +136 -0
- data/lib/bfs/ftp.rb +1 -0
- data/spec/bfs/bucket/ftp_spec.rb +26 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -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
|
data/bfs-ftp.gemspec
ADDED
@@ -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
|
data/lib/bfs/ftp.rb
ADDED
@@ -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
|