winrm-fs 1.2.0 → 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 +5 -5
- data/.rubocop.yml +3 -0
- data/.rubocop_todo.yml +0 -7
- data/.travis.yml +1 -1
- data/README.md +4 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/appveyor.yml +1 -1
- data/changelog.md +8 -0
- data/lib/winrm-fs/core/file_transporter.rb +65 -25
- data/lib/winrm-fs/core/tmp_zip.rb +1 -1
- data/lib/winrm-fs/file_manager.rb +2 -2
- data/spec/integration/file_manager_spec.rb +16 -0
- data/spec/spec_helper.rb +0 -1
- data/winrm-fs.gemspec +5 -5
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d7898b5512c391163a77d694860db51a5c15c5745031c2b34c0cd181a9bbda37
|
|
4
|
+
data.tar.gz: 87864314b0863331944c604d26c0721db568db238da87923b836d80097531dad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d468205639de56be5fcf4c4896a823f96760e03e23153b6e09cc9c1bc2779725d84f429a759d67088e622a288a3e002bb528f9e23749cded6416baac38b26614
|
|
7
|
+
data.tar.gz: b8787f4e3ae986aa32ae324cd1e6113081b83cb291ba519b027dea7ee67f0c4a0d9d15e50e38222328d94829735156a525c066cab56966c6e92de25754efc5b4
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
|
@@ -34,13 +34,6 @@ Naming/HeredocDelimiterNaming:
|
|
|
34
34
|
- 'spec/matchers.rb'
|
|
35
35
|
- 'winrm-fs.gemspec'
|
|
36
36
|
|
|
37
|
-
# Offense count: 2
|
|
38
|
-
# Cop supports --auto-correct.
|
|
39
|
-
# Configuration parameters: AutoCorrect.
|
|
40
|
-
Performance/HashEachMethods:
|
|
41
|
-
Exclude:
|
|
42
|
-
- 'lib/winrm-fs/core/file_transporter.rb'
|
|
43
|
-
|
|
44
37
|
# Offense count: 1
|
|
45
38
|
# Configuration parameters: .
|
|
46
39
|
# SupportedStyles: annotated, template, unannotated
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](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/Rakefile
CHANGED
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.3.0
|
data/appveyor.yml
CHANGED
data/changelog.md
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
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
|
+
|
|
7
|
+
# 1.2.1
|
|
8
|
+
- Correctly handle unicode filenames
|
|
9
|
+
|
|
2
10
|
# 1.2.0
|
|
3
11
|
- Add ability to download directories
|
|
4
12
|
|
|
@@ -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
|
|
@@ -56,6 +65,7 @@ module WinRM
|
|
|
56
65
|
@shell = shell
|
|
57
66
|
@logger = shell.logger
|
|
58
67
|
@id_generator = opts.fetch(:id_generator) { -> { SecureRandom.uuid } }
|
|
68
|
+
Zip.unicode_names = true
|
|
59
69
|
end
|
|
60
70
|
|
|
61
71
|
# Uploads a collection of files and/or directories to the remote host.
|
|
@@ -66,17 +76,16 @@ module WinRM
|
|
|
66
76
|
# * progress yields block like net-scp progress
|
|
67
77
|
# * final API: def upload(locals, remote, _options = {}, &_progress)
|
|
68
78
|
#
|
|
69
|
-
# @param locals [Array<String>,String] one or more
|
|
70
|
-
# directory paths
|
|
79
|
+
# @param locals [Array<String>,String,StringIO] one or more
|
|
80
|
+
# local file or directory paths, StringIO objects also accepted
|
|
71
81
|
# @param remote [String] the base destination path on the remote host
|
|
72
82
|
# @return [Hash] report hash, keyed by the local SHA1 digest
|
|
73
83
|
def upload(locals, remote)
|
|
74
84
|
files = nil
|
|
75
85
|
report = nil
|
|
76
86
|
remote = remote.to_s
|
|
77
|
-
|
|
78
87
|
elapsed1 = Benchmark.measure do
|
|
79
|
-
files = make_files_hash(
|
|
88
|
+
files = make_files_hash([locals].flatten, remote)
|
|
80
89
|
report = check_files(files)
|
|
81
90
|
merge_with_report!(files, report)
|
|
82
91
|
reconcile_destinations!(files)
|
|
@@ -182,16 +191,15 @@ module WinRM
|
|
|
182
191
|
# Adds an entry to a files Hash (keyed by local SHA1 digest) for a file.
|
|
183
192
|
#
|
|
184
193
|
# @param hash [Hash] hash to be mutated
|
|
185
|
-
# @param local [String] file path
|
|
194
|
+
# @param local [String, StringIO] file path or StringIO object
|
|
186
195
|
# @param remote [String] path to destination on remote host
|
|
187
196
|
# @api private
|
|
188
197
|
def add_file_hash!(hash, local, remote)
|
|
189
198
|
logger.debug "creating hash for file #{remote}"
|
|
190
|
-
|
|
191
199
|
hash[sha1sum(local)] = {
|
|
192
200
|
'src' => local,
|
|
193
201
|
'dst' => remote,
|
|
194
|
-
'size' => File.size(local)
|
|
202
|
+
'size' => local.is_a?(StringIO) ? local.size : File.size(local)
|
|
195
203
|
}
|
|
196
204
|
end
|
|
197
205
|
|
|
@@ -222,7 +230,7 @@ module WinRM
|
|
|
222
230
|
sha1,
|
|
223
231
|
{
|
|
224
232
|
'target' => data.fetch('tmpzip', data['dst']),
|
|
225
|
-
'src_basename' => File.basename(data['src']),
|
|
233
|
+
'src_basename' => data['src'].is_a?(StringIO) ? data['dst'] : File.basename(data['src']),
|
|
226
234
|
'dst' => data['dst']
|
|
227
235
|
}
|
|
228
236
|
]
|
|
@@ -301,33 +309,61 @@ module WinRM
|
|
|
301
309
|
# digest. Each file entry has a source and destination set, at a
|
|
302
310
|
# minimum.
|
|
303
311
|
#
|
|
304
|
-
# @param locals [Array<String>] a collection of local files
|
|
305
|
-
# directories
|
|
312
|
+
# @param locals [Array<String,StringIO>] a collection of local files,
|
|
313
|
+
# directories or StringIO objects
|
|
306
314
|
# @param remote [String] the base destination path on the remote host
|
|
307
315
|
# @return [Hash] files hash, keyed by the local SHA1 digest
|
|
308
316
|
# @api private
|
|
309
317
|
def make_files_hash(locals, remote)
|
|
310
318
|
hash = {}
|
|
319
|
+
check_locals_array(locals)
|
|
311
320
|
locals.each do |local|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
expanded += local[-1] if local.end_with?('/', '\\')
|
|
315
|
-
|
|
316
|
-
if File.file?(expanded)
|
|
317
|
-
add_file_hash!(hash, expanded, remote)
|
|
318
|
-
elsif File.directory?(expanded)
|
|
319
|
-
add_directory_hash!(hash, expanded, remote)
|
|
321
|
+
if local.is_a?(StringIO)
|
|
322
|
+
add_file_hash!(hash, local, remote)
|
|
320
323
|
else
|
|
321
|
-
|
|
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
|
|
322
334
|
end
|
|
323
335
|
end
|
|
324
336
|
hash
|
|
325
337
|
end
|
|
326
338
|
|
|
327
|
-
#
|
|
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
|
|
328
360
|
# @api private
|
|
329
361
|
def sha1sum(local)
|
|
330
|
-
|
|
362
|
+
if local.is_a?(StringIO)
|
|
363
|
+
Digest::SHA1.hexdigest(local.string)
|
|
364
|
+
else
|
|
365
|
+
Digest::SHA1.file(local).hexdigest
|
|
366
|
+
end
|
|
331
367
|
end
|
|
332
368
|
|
|
333
369
|
# Destructively merges a report Hash into an existing files Hash.
|
|
@@ -432,7 +468,7 @@ module WinRM
|
|
|
432
468
|
# ClearScriptBlockCache to clear it.
|
|
433
469
|
$bindingFlags= [Reflection.BindingFlags] "NonPublic,Static"
|
|
434
470
|
$method = [scriptblock].GetMethod("ClearScriptBlockCache", $bindingFlags)
|
|
435
|
-
|
|
471
|
+
EOS
|
|
436
472
|
)
|
|
437
473
|
|
|
438
474
|
while input_io.read(read_size, buffer)
|
|
@@ -458,7 +494,7 @@ module WinRM
|
|
|
458
494
|
|
|
459
495
|
# Uploads a local file.
|
|
460
496
|
#
|
|
461
|
-
# @param src [String] path to a local file
|
|
497
|
+
# @param src [String, StringIO] path to a local file or StringIO object
|
|
462
498
|
# @param dest [String] path to the file on the remote host
|
|
463
499
|
# @return [Integer,Integer] the number of resulting upload chunks and
|
|
464
500
|
# the number of bytes transferred to the remote host
|
|
@@ -468,8 +504,12 @@ module WinRM
|
|
|
468
504
|
chunks = 0
|
|
469
505
|
bytes = 0
|
|
470
506
|
elapsed = Benchmark.measure do
|
|
471
|
-
|
|
472
|
-
chunks, bytes = stream_upload(
|
|
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
|
|
473
513
|
end
|
|
474
514
|
end
|
|
475
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.
|
|
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),
|
|
@@ -83,7 +83,7 @@ module WinRM
|
|
|
83
83
|
# 'C:/Windows/Temp'
|
|
84
84
|
# @return [String] Full path to the temp directory
|
|
85
85
|
def temp_dir
|
|
86
|
-
@
|
|
86
|
+
@temp_dir ||= begin
|
|
87
87
|
(@connection.shell(:powershell) { |e| e.run('$env:TEMP') }).stdout.chomp.tr('\\', '/')
|
|
88
88
|
end
|
|
89
89
|
end
|
|
@@ -116,7 +116,7 @@ module WinRM
|
|
|
116
116
|
private
|
|
117
117
|
|
|
118
118
|
def download_dir(remote_path, local_path, first)
|
|
119
|
-
local_path = File.join(local_path, File.basename(remote_path)) if first
|
|
119
|
+
local_path = File.join(local_path, File.basename(remote_path.to_s)) if first
|
|
120
120
|
FileUtils.mkdir_p(local_path) unless File.directory?(local_path)
|
|
121
121
|
command = "Get-ChildItem #{remote_path} | Select-Object Name"
|
|
122
122
|
@connection.shell(:powershell) { |e| e.run(command) }.stdout.strip.split(/\n/).drop(2).each do |file|
|
|
@@ -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)
|
data/spec/spec_helper.rb
CHANGED
data/winrm-fs.gemspec
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
require 'date'
|
|
2
2
|
|
|
3
|
-
version = File.read(File.expand_path('
|
|
3
|
+
version = File.read(File.expand_path('VERSION', __dir__)).strip
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |s|
|
|
6
6
|
s.platform = Gem::Platform::RUBY
|
|
7
7
|
s.name = 'winrm-fs'
|
|
8
8
|
s.version = version
|
|
9
|
-
s.date
|
|
9
|
+
s.date = Date.today.to_s
|
|
10
10
|
|
|
11
11
|
s.author = ['Shawn Neal', 'Matt Wrock']
|
|
12
12
|
s.email = ['sneal@sneal.net', 'matt@mattwrock.com']
|
|
13
13
|
s.homepage = 'http://github.com/WinRb/winrm-fs'
|
|
14
14
|
|
|
15
15
|
s.summary = 'WinRM File System'
|
|
16
|
-
s.description
|
|
16
|
+
s.description = <<-EOF
|
|
17
17
|
Ruby library for file system operations via Windows Remote Management
|
|
18
18
|
EOF
|
|
19
19
|
|
|
20
20
|
s.files = `git ls-files`.split(/\n/)
|
|
21
21
|
s.require_path = 'lib'
|
|
22
|
-
s.rdoc_options
|
|
22
|
+
s.rdoc_options = %w[-x test/ -x examples/]
|
|
23
23
|
s.extra_rdoc_files = %w[README.md LICENSE]
|
|
24
24
|
|
|
25
25
|
s.bindir = 'bin'
|
|
26
26
|
s.executables = ['rwinrmcp']
|
|
27
|
-
s.required_ruby_version
|
|
27
|
+
s.required_ruby_version = '>= 2.2.0'
|
|
28
28
|
s.add_runtime_dependency 'erubis', '~> 2.7'
|
|
29
29
|
s.add_runtime_dependency 'logging', ['>= 1.6.1', '< 3.0']
|
|
30
30
|
s.add_runtime_dependency 'rubyzip', '~> 1.1'
|
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.
|
|
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-
|
|
12
|
+
date: 2018-08-31 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: erubis
|
|
@@ -189,7 +189,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
189
189
|
requirements:
|
|
190
190
|
- - ">="
|
|
191
191
|
- !ruby/object:Gem::Version
|
|
192
|
-
version: 2.
|
|
192
|
+
version: 2.2.0
|
|
193
193
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
194
194
|
requirements:
|
|
195
195
|
- - ">="
|
|
@@ -197,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
197
197
|
version: '0'
|
|
198
198
|
requirements: []
|
|
199
199
|
rubyforge_project:
|
|
200
|
-
rubygems_version: 2.6
|
|
200
|
+
rubygems_version: 2.7.6
|
|
201
201
|
signing_key:
|
|
202
202
|
specification_version: 4
|
|
203
203
|
summary: WinRM File System
|