winrm-fs 1.2.1 → 1.3.0

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
  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