winrm-fs 1.2.1 → 1.3.0

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
  SHA256:
3
- metadata.gz: 906e09af384b4685d053fdd0654978757d26e3d2d281841706db04c78c44139c
4
- data.tar.gz: d708a910d83ecfde7357a4ba9b42c138d375264c7ca126705fbfbacc5e7e842e
3
+ metadata.gz: d7898b5512c391163a77d694860db51a5c15c5745031c2b34c0cd181a9bbda37
4
+ data.tar.gz: 87864314b0863331944c604d26c0721db568db238da87923b836d80097531dad
5
5
  SHA512:
6
- metadata.gz: b1ad3a5cf262cfe8ea47db2072600c328cb672816b122fe9340afacb364fefc620de0467d9d65d1bb1290ce215cbe521d74ba852307ea94edd7fa31765e11dab
7
- data.tar.gz: 6cf1d092f268dc0d0afba76653e56df120938fde974a597ee1d930aa64bdc553bb9254e7a5f4f614d654255ce01acc2b53efd336a6ba5ea0ae78fe6f40fb49b3
6
+ metadata.gz: d468205639de56be5fcf4c4896a823f96760e03e23153b6e09cc9c1bc2779725d84f429a759d67088e622a288a3e002bb528f9e23749cded6416baac38b26614
7
+ data.tar.gz: b8787f4e3ae986aa32ae324cd1e6113081b83cb291ba519b027dea7ee67f0c4a0d9d15e50e38222328d94829735156a525c066cab56966c6e92de25754efc5b4
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Build status](https://ci.appveyor.com/api/projects/status/wm6apa8ojfhfmwsf?svg=true)](https://ci.appveyor.com/project/winrb/winrm-fs)
5
5
 
6
6
  ## Uploading files
7
- Files may be copied from the local machine to the winrm endpoint. Individual files or directories, as well as arrays of files and directories may be specified:
7
+ Files may be copied from the local machine to the winrm endpoint. Individual files or directories, as well as arrays of files and directories may be specified. Data from a `StringIO` object may also be uploaded to a remote file.
8
8
  ```ruby
9
9
  require 'winrm-fs'
10
10
 
@@ -17,6 +17,9 @@ file_manager.upload('file.txt', 'c:/file.txt')
17
17
  # upload the my_dir directory to c:/foo/my_dir
18
18
  file_manager.upload('/Users/sneal/my_dir', 'c:/foo/my_dir')
19
19
 
20
+ # upload from an in-memory buffer
21
+ file_manager.upload(StringIO.new('some data to upload'), 'c:/file.txt')
22
+
20
23
  # upload multiple directories and a file to c:\programData
21
24
  file_manager.upload([
22
25
  '/Users/sneal/foo1',
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.1
1
+ 1.3.0
@@ -1,4 +1,9 @@
1
1
  # WinRM-fs Gem Changelog
2
+ # 1.3.0
3
+ - Upload from StringIO object
4
+ - Add missing winrm/exceptions require in file_transporter
5
+ - Use correct way to relativize paths of Zip entries
6
+
2
7
  # 1.2.1
3
8
  - Correctly handle unicode filenames
4
9
 
@@ -21,6 +21,7 @@ require 'digest'
21
21
  require 'securerandom'
22
22
  require 'stringio'
23
23
 
24
+ require 'winrm/exceptions'
24
25
  require 'winrm-fs/core/tmp_zip'
25
26
 
26
27
  module WinRM
@@ -32,6 +33,14 @@ module WinRM
32
33
  class FileTransporterFailed < ::WinRM::WinRMError; end
33
34
  # rubocop:disable MethodLength, AbcSize, ClassLength
34
35
 
36
+ # Exception for the case where upload source contains more than one
37
+ # StringIO object, or a combination of file/directory paths and StringIO object
38
+ class UploadSourceError < StandardError
39
+ def initialize(msg = 'Only a single StringIO object may be uploaded.')
40
+ super
41
+ end
42
+ end
43
+
35
44
  # Object which can upload one or more files or directories to a remote
36
45
  # host over WinRM using PowerShell scripts and CMD commands. Note that
37
46
  # this form of file transfer is *not* ideal and extremely costly on both
@@ -67,17 +76,16 @@ module WinRM
67
76
  # * progress yields block like net-scp progress
68
77
  # * final API: def upload(locals, remote, _options = {}, &_progress)
69
78
  #
70
- # @param locals [Array<String>,String] one or more local file or
71
- # directory paths
79
+ # @param locals [Array<String>,String,StringIO] one or more
80
+ # local file or directory paths, StringIO objects also accepted
72
81
  # @param remote [String] the base destination path on the remote host
73
82
  # @return [Hash] report hash, keyed by the local SHA1 digest
74
83
  def upload(locals, remote)
75
84
  files = nil
76
85
  report = nil
77
86
  remote = remote.to_s
78
-
79
87
  elapsed1 = Benchmark.measure do
80
- files = make_files_hash(Array(locals), remote)
88
+ files = make_files_hash([locals].flatten, remote)
81
89
  report = check_files(files)
82
90
  merge_with_report!(files, report)
83
91
  reconcile_destinations!(files)
@@ -183,16 +191,15 @@ module WinRM
183
191
  # Adds an entry to a files Hash (keyed by local SHA1 digest) for a file.
184
192
  #
185
193
  # @param hash [Hash] hash to be mutated
186
- # @param local [String] file path
194
+ # @param local [String, StringIO] file path or StringIO object
187
195
  # @param remote [String] path to destination on remote host
188
196
  # @api private
189
197
  def add_file_hash!(hash, local, remote)
190
198
  logger.debug "creating hash for file #{remote}"
191
-
192
199
  hash[sha1sum(local)] = {
193
200
  'src' => local,
194
201
  'dst' => remote,
195
- 'size' => File.size(local)
202
+ 'size' => local.is_a?(StringIO) ? local.size : File.size(local)
196
203
  }
197
204
  end
198
205
 
@@ -223,7 +230,7 @@ module WinRM
223
230
  sha1,
224
231
  {
225
232
  'target' => data.fetch('tmpzip', data['dst']),
226
- 'src_basename' => File.basename(data['src']),
233
+ 'src_basename' => data['src'].is_a?(StringIO) ? data['dst'] : File.basename(data['src']),
227
234
  'dst' => data['dst']
228
235
  }
229
236
  ]
@@ -302,33 +309,61 @@ module WinRM
302
309
  # digest. Each file entry has a source and destination set, at a
303
310
  # minimum.
304
311
  #
305
- # @param locals [Array<String>] a collection of local files or
306
- # directories
312
+ # @param locals [Array<String,StringIO>] a collection of local files,
313
+ # directories or StringIO objects
307
314
  # @param remote [String] the base destination path on the remote host
308
315
  # @return [Hash] files hash, keyed by the local SHA1 digest
309
316
  # @api private
310
317
  def make_files_hash(locals, remote)
311
318
  hash = {}
319
+ check_locals_array(locals)
312
320
  locals.each do |local|
313
- local = local.to_s
314
- expanded = File.expand_path(local)
315
- expanded += local[-1] if local.end_with?('/', '\\')
316
-
317
- if File.file?(expanded)
318
- add_file_hash!(hash, expanded, remote)
319
- elsif File.directory?(expanded)
320
- add_directory_hash!(hash, expanded, remote)
321
+ if local.is_a?(StringIO)
322
+ add_file_hash!(hash, local, remote)
321
323
  else
322
- raise Errno::ENOENT, "No such file or directory #{expanded}"
324
+ local = local.to_s
325
+ expanded = File.expand_path(local)
326
+ expanded += local[-1] if local.end_with?('/', '\\')
327
+ if File.file?(expanded)
328
+ add_file_hash!(hash, expanded, remote)
329
+ elsif File.directory?(expanded)
330
+ add_directory_hash!(hash, expanded, remote)
331
+ else
332
+ raise Errno::ENOENT, "No such file or directory #{expanded}"
333
+ end
323
334
  end
324
335
  end
325
336
  hash
326
337
  end
327
338
 
328
- # @return [String] the SHA1 digest of a local file
339
+ # Ensure that only a single StringIO object is uploaded at a time
340
+ # This is necessary because the contents of the buffer will be written
341
+ # to the destination.
342
+ # @param locals [Array<String,StringIO>] a collection of local files,
343
+ # directories or StringIO objects
344
+ # @api private
345
+ def check_locals_array(locals)
346
+ string_io = false
347
+ path = false
348
+ locals.each do |local|
349
+ raise UploadSourceError if string_io
350
+ if local.is_a?(StringIO)
351
+ string_io = true
352
+ else
353
+ path = true
354
+ end
355
+ raise UploadSourceError if string_io && path
356
+ end
357
+ end
358
+
359
+ # @return [String] the SHA1 digest of a local file or StringIO
329
360
  # @api private
330
361
  def sha1sum(local)
331
- Digest::SHA1.file(local).hexdigest
362
+ if local.is_a?(StringIO)
363
+ Digest::SHA1.hexdigest(local.string)
364
+ else
365
+ Digest::SHA1.file(local).hexdigest
366
+ end
332
367
  end
333
368
 
334
369
  # Destructively merges a report Hash into an existing files Hash.
@@ -459,7 +494,7 @@ module WinRM
459
494
 
460
495
  # Uploads a local file.
461
496
  #
462
- # @param src [String] path to a local file
497
+ # @param src [String, StringIO] path to a local file or StringIO object
463
498
  # @param dest [String] path to the file on the remote host
464
499
  # @return [Integer,Integer] the number of resulting upload chunks and
465
500
  # the number of bytes transferred to the remote host
@@ -469,8 +504,12 @@ module WinRM
469
504
  chunks = 0
470
505
  bytes = 0
471
506
  elapsed = Benchmark.measure do
472
- File.open(src, 'rb') do |io|
473
- chunks, bytes = stream_upload(io, dest, &block)
507
+ if src.is_a?(StringIO)
508
+ chunks, bytes = stream_upload(src, dest, &block)
509
+ else
510
+ File.open(src, 'rb') do |io|
511
+ chunks, bytes = stream_upload(io, dest, &block)
512
+ end
474
513
  end
475
514
  end
476
515
  logger.debug(
@@ -125,7 +125,7 @@ module WinRM
125
125
  # @api private
126
126
  def produce_zip_entries(zos)
127
127
  entries.each do |entry|
128
- entry_path = entry.sub(/#{dir}\//i, '')
128
+ entry_path = entry.relative_path_from(dir)
129
129
  logger.debug "+++ Adding #{entry_path}"
130
130
  zos.put_next_entry(
131
131
  zip_entry(entry_path),
@@ -86,11 +86,27 @@ describe WinRM::FS::FileManager do
86
86
 
87
87
  context 'upload file' do
88
88
  let(:dest_file) { Pathname.new(File.join(dest_dir, File.basename(this_file))) }
89
+ let(:from_memory) { StringIO.new('Upload From Memory') }
89
90
 
90
91
  before(:each) do
91
92
  expect(subject.delete(dest_dir)).to be true
92
93
  end
93
94
 
95
+ it 'should upload a single StringIO object to a remote file' do
96
+ subject.upload(from_memory, dest_file)
97
+ expect(subject).to have_created(dest_file).with_content(from_memory.string)
98
+ end
99
+
100
+ it 'should error if multiple StringIO objects passed to upload' do
101
+ expect { subject.upload([from_memory, from_memory], dest_file) }
102
+ .to raise_error(WinRM::FS::Core::UploadSourceError)
103
+ end
104
+
105
+ it 'should error if both a StringIO object and a file path passed to upload' do
106
+ expect { subject.upload([from_memory, this_file], dest_file) }
107
+ .to raise_error(WinRM::FS::Core::UploadSourceError)
108
+ end
109
+
94
110
  it 'should upload the specified file' do
95
111
  subject.upload(this_file, dest_file)
96
112
  expect(subject).to have_created(dest_file).with_content(this_file)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: winrm-fs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shawn Neal
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-07-30 00:00:00.000000000 Z
12
+ date: 2018-08-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: erubis