xftp 0.3.3 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0959975377a49b36adef1ae39718a0b40064a3da
4
- data.tar.gz: d347086da5b53feb27daea0519e5007b3c2b8238
3
+ metadata.gz: 519e2c6a592998d81cfcff39a0b07896de6d107a
4
+ data.tar.gz: 7c964302e0290616bb71e32fa2da427804c0a839
5
5
  SHA512:
6
- metadata.gz: 5d3313732ffa95e9703406ef8512c3b05c6a3d98949e84e72d8e740cbbe30c034bd57cf16cd01f8f611a10c09b91e4fedf9758ae7f4f21cb5b40e1e24bdbe932
7
- data.tar.gz: c6529b38a432105281887a42a7c15acb2e27cb8b7f541400acbcf7b04fcf4f8fc3e55efa91f61317df2ac76095771a67aafd8f585e0ed30d65541a4b5e4f757f
6
+ metadata.gz: 21e2e2c9f5d002ea1cbb48bafb28fb08f1e6645ba5eac6d1131dcf1093b8b1f1458cbc0ea077c951cdf6ac4267e38fdd9728f0f46b33a4432504900a91cf3b4a
7
+ data.tar.gz: 06b5984a465cefa1e955550d5dfc0859d5f995fa7ce3294c7f7985e66c2e4cf9afcbc3cd4a31e86d9047c335f28952932bf10598386182f7acfa8c31f2703249
data/README.md CHANGED
@@ -17,8 +17,9 @@ or
17
17
  $ gem install xftp
18
18
  ```
19
19
 
20
- ## Usage
20
+ ## Usage examples
21
21
 
22
+ Basic example:
22
23
  ```ruby
23
24
  XFTP.start('ftps://hostname', credentials: { login: 'login', password: 'pass' }) do |x|
24
25
  x.chdir 'remote-src-path'
@@ -32,6 +33,37 @@ XFTP.start('ftps://hostname', credentials: { login: 'login', password: 'pass' })
32
33
  end
33
34
  ```
34
35
 
36
+ Connection as anonymous with emtpy password, checking remote dir existence, globbing and getting `StringIO`'s:
37
+ ```ruby
38
+ XFTP.start('ftp://hostname') do |x|
39
+ x.mkdir 'some-dir' unless x.exist? 'some-dir'
40
+ x.glob '*.csv' do |filename|
41
+ io = x.get filename
42
+ end
43
+ end
44
+ ```
45
+
46
+ Example using `each_io`:
47
+ ```ruby
48
+ XFTP.start('ftps://hostname', credentials: { login: 'login', password: 'password' }) do |x|
49
+ x.chdir 'some-dir'
50
+ x.each_io do |filename, io|
51
+ # do smth with it
52
+ end
53
+ end
54
+ ```
55
+
56
+ Wihout block argument (ntoe that you should rely on you local execution context objects):
57
+ ```ruby
58
+ XFTP.start('ftps://hostname', credentials: credentials)
59
+ chdir 'blahblah'
60
+ each_file do |filename|
61
+ download filename, to: File.join('local-dir', filename)
62
+ move filename, to: File.join('remote-archive-path', filename)
63
+ end
64
+ end
65
+ ```
66
+
35
67
  ## Development
36
68
 
37
69
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -7,6 +7,8 @@ module XFTP
7
7
  # @note It isn't tested on Windows OS and chances are that it won't work,
8
8
  # that's why it is implemented as a separate "command"
9
9
  class Glob
10
+ NO_SUCH_FILE_OR_DIRECTORY_CODE = 450
11
+
10
12
  def initialize(ftp)
11
13
  @ftp = ftp
12
14
  end
@@ -17,6 +19,9 @@ module XFTP
17
19
  # @param [Proc] callback
18
20
  def call(pattern, &callback)
19
21
  @ftp.nlst(pattern).each { |filename| callback.call(filename) }
22
+ rescue Net::FTPTempError => err
23
+ code = err.to_s[0, 3].try(:to_i)
24
+ raise err unless code == NO_SUCH_FILE_OR_DIRECTORY_CODE
20
25
  end
21
26
  end
22
27
  end
@@ -29,6 +29,12 @@ module XFTP
29
29
  close
30
30
  log 'done'
31
31
  end
32
+
33
+ protected
34
+
35
+ def ensure_relative_path!(operation, path)
36
+ fail ArgumentError, "Absolute path can't be specified for `#{operation}`" if Pathname.new(path).absolute?
37
+ end
32
38
  end
33
39
  end
34
40
  end
@@ -1,5 +1,4 @@
1
1
  require 'active_support/core_ext/hash/deep_merge'
2
- require 'forwardable'
3
2
  require 'net/ftp'
4
3
 
5
4
  require 'xftp/session/base'
@@ -10,12 +9,6 @@ module XFTP
10
9
  # FTP session adapter
11
10
  # @api private
12
11
  class FTP < Base
13
- extend Forwardable
14
-
15
- # Delegate methods which have the same method signature
16
- # directly to Net::FTP session
17
- def_delegators :@ftp, :chdir, :mkdir, :rmdir
18
-
19
12
  # Creates an FTP session adapter instance
20
13
  # @param [URI] uri the remote uri
21
14
  # @param [Hash] settings the adapter connection settings
@@ -30,14 +23,40 @@ module XFTP
30
23
  options.each { |key, val| @ftp.public_send("#{key}=", val) }
31
24
  end
32
25
 
26
+ # Changes the current (remote) working directory
27
+ # @param [String] path the relative (remote) path
28
+ def chdir(path)
29
+ ensure_relative_path! :chdir, path
30
+ @ftp.chdir path
31
+ end
32
+
33
+ # Creates a remote directory
34
+ # @param [String] dirname the name of new directory
35
+ # relative to the current (remote) working directory
36
+ def mkdir(dirname)
37
+ ensure_relative_path! :mkdir, dirname
38
+ @ftp.mkdir dirname
39
+ end
40
+
41
+ # Removes the remote directory
42
+ # @param [String] dirname the name of directory to be removed
43
+ def rmdir(dirname)
44
+ ensure_relative_path! :rmdir, dirname
45
+ @ftp.rmdir dirname
46
+ end
47
+
33
48
  # @return [Boolean] `true` if the argument refers to a directory on the remote host
34
49
  def exists?(dirname)
35
50
  entries.include? dirname
36
51
  end
37
52
 
53
+ # HACK: It looks ridiculous, but its the only way to find out
54
+ # if the given remote path is a file or directory
55
+
38
56
  # @return [Boolean] `true` if the argument refers to
39
57
  # a directory on the remote host
40
58
  def directory?(path)
59
+ ensure_relative_path! :directory?, path
41
60
  chdir path
42
61
  chdir '..'
43
62
  true
@@ -65,6 +84,21 @@ module XFTP
65
84
  files.each { |filename| yield filename }
66
85
  end
67
86
 
87
+ # Calls the block once for each entry in the current directory
88
+ # on the remote server and yields a filename and `StringIO` object to the block
89
+ def each_io
90
+ each_file do |filename|
91
+ io = get filename
92
+ yield filename, io
93
+ end
94
+ end
95
+
96
+ # Downloads file into IO object
97
+ # @return [StringIO] the remote file data
98
+ def get(filename)
99
+ @ftp.getbinaryfile(filename, nil)
100
+ end
101
+
68
102
  # @see XFTP::Operations::FTP::Glob
69
103
  def glob(pattern, &callback)
70
104
  Operations::FTP::Glob.new(@ftp).call(pattern, &callback)
@@ -8,6 +8,31 @@ module XFTP
8
8
  # SFTP session adapter
9
9
  # @api private
10
10
  class SFTP < Base
11
+ # Helper class for progress monitoring
12
+ class ProgressHandler
13
+ include Helpers::Logging
14
+
15
+ def on_open(_downloader, file)
16
+ log "starting download: #{file.remote} -> #{file.local} (#{file.size} bytes)"
17
+ end
18
+
19
+ def on_get(_downloader, file, offset, data)
20
+ log "writing #{data.length} bytes to #{file.local} starting at #{offset}"
21
+ end
22
+
23
+ def on_close(_downloader, file)
24
+ log "finished with #{file.remote}"
25
+ end
26
+
27
+ def on_mkdir(_downloader, path)
28
+ log "creating directory #{path}"
29
+ end
30
+
31
+ def on_finish(_downloader)
32
+ log 'done'
33
+ end
34
+ end
35
+
11
36
  # Default flags for rename operation
12
37
  RENAME_OPERATION_FLAGS = 0x0004
13
38
  # Default flags for glob operation
@@ -26,6 +51,7 @@ module XFTP
26
51
  # Changes the current (remote) working directory
27
52
  # @param [String] path the relative (remote) path
28
53
  def chdir(path)
54
+ ensure_relative_path! :chdir, path
29
55
  @path += path
30
56
  end
31
57
 
@@ -35,9 +61,17 @@ module XFTP
35
61
  # @param [Hash] attrs the attributes of new directory
36
62
  # supported by the the version of SFTP protocol in use
37
63
  def mkdir(dirname, attrs = {})
64
+ ensure_relative_path! :mkdir, path
38
65
  @sftp.mkdir!(remote_path(dirname), attrs)
39
66
  end
40
67
 
68
+ # Removes the remote directory
69
+ # @param [String] dirname the name of directory to be removed
70
+ def rmdir(dirname)
71
+ ensure_relative_path! :rmdir, path
72
+ @sftp.rmdir! remote_path(dirname)
73
+ end
74
+
41
75
  # @return [Boolean] `true` if the file exists
42
76
  # in a current working directory on the remote host
43
77
  def exists?(filename)
@@ -47,6 +81,7 @@ module XFTP
47
81
  # @return [Boolean] `true` if the argument refers to
48
82
  # a directory on the remote host
49
83
  def directory?(path)
84
+ ensure_relative_path! :directory?, path
50
85
  @sftp.file.directory? remote_path(path)
51
86
  end
52
87
 
@@ -56,12 +91,6 @@ module XFTP
56
91
  !directory?(path)
57
92
  end
58
93
 
59
- # Removes the remote directory
60
- # @param [String] dirname the name of directory to be removed
61
- def rmdir(dirname)
62
- @sftp.rmdir! remote_path(dirname)
63
- end
64
-
65
94
  # Renames (moves) a file on the server
66
95
  # @param [String] from the path to move from
67
96
  # @param [String] to the path to move to
@@ -79,6 +108,21 @@ module XFTP
79
108
  end
80
109
  end
81
110
 
111
+ # Calls the block once for each entry in the current directory
112
+ # on the remote server and (asynchronously) yields a filename and `StringIO` object to the block
113
+ def each_io
114
+ each_file do |filename|
115
+ io = get filename
116
+ yield filename, io
117
+ end
118
+ end
119
+
120
+ # Downloads file into IO object
121
+ # @return [StringIO] the remote file data
122
+ def get(filename)
123
+ @sftp.download!(remote_path(filename), nil, progress: ProgressHandler)
124
+ end
125
+
82
126
  # For more info (see Dir#glob), it's almost of the same nature
83
127
  # @param [String] pattern the search pattern relative
84
128
  # the the current working directory
@@ -105,8 +149,7 @@ module XFTP
105
149
  entries.reject { |filename| directory? filename }
106
150
  end
107
151
 
108
- # @return [Array<String>] an array of entries (including directories)
109
- # in the remote directory
152
+ # @return [Array<String>] an array of entries (including directories) in the remote directory
110
153
  def entries
111
154
  @sftp.dir.entries(@path.to_s).map(&:name)
112
155
  end
data/lib/xftp/version.rb CHANGED
@@ -2,8 +2,8 @@ module XFTP
2
2
  # Gem version builder module
3
3
  module VERSION
4
4
  MAJOR = 0
5
- MINOR = 3
6
- PATCH = 3
5
+ MINOR = 4
6
+ PATCH = 1
7
7
  SUFFIX = ''
8
8
 
9
9
  NUMBER = [MAJOR, MINOR, PATCH].compact.join('.')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xftp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vasiliy Yorkin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-04-28 00:00:00.000000000 Z
11
+ date: 2015-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -239,6 +239,6 @@ rubyforge_project:
239
239
  rubygems_version: 2.2.2
240
240
  signing_key:
241
241
  specification_version: 4
242
- summary: xftp-0.3.3
242
+ summary: xftp-0.4.1
243
243
  test_files: []
244
244
  has_rdoc: