xftp 0.3.3 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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: