From 6858c89eba234c8c92429c76ec8ae88ce1f09d23 Mon Sep 17 00:00:00 2001 From: Baptiste Courtois Date: Thu, 4 Dec 2014 20:36:15 +0100 Subject: [PATCH] Add ability to compress files for faster transfert --- lib/vagrant-winrm/commands/winrm_upload.rb | 81 +++++++++++++++++----- lib/version.rb | 2 +- vagrant-winrm.gemspec | 10 +-- 3 files changed, 69 insertions(+), 24 deletions(-) diff --git a/lib/vagrant-winrm/commands/winrm_upload.rb b/lib/vagrant-winrm/commands/winrm_upload.rb index 20f09ae..075e2cc 100644 --- a/lib/vagrant-winrm/commands/winrm_upload.rb +++ b/lib/vagrant-winrm/commands/winrm_upload.rb @@ -8,19 +8,77 @@ def self.synopsis end def execute - options = { temporary: false } + options = { temporary: false, compress: false } + source, destination, argv = parse_args options + return unless source || destination + + # Execute the actual WinRM + with_target_vms(argv, single_target: true) do |vm| + + raise Errors::ConfigurationError, { :communicator => vm.config.vm.communicator } if vm.config.vm.communicator != :winrm + + tmp_dest = get_remote_temp_folder(vm) if options[:temporary] || options[:compress] + + dest_file = options[:temporary] ? ::File.join(tmp_dest, destination) : destination + $stdout.print dest_file if options[:temporary] + + @logger.debug("Uploading #{source} to #{destination}") + if options[:compress] + source_is_dir = ::File.directory? source + source = compress(source, source_is_dir) + + dest_dir = source_is_dir || dest_file.end_with?('/') || dest_file.end_with?('\\') ? dest_file : ::File.dirname(dest_file) + remote_tgz_path = ::File.join(::File.dirname(tmp_dest), ::File.basename(source)) + vm.communicate.upload(source, remote_tgz_path) + return vm.communicate.execute("New-Item '#{dest_dir}' -type directory -force; tar -xzf '#{remote_tgz_path}' -C '#{dest_dir}'; ") + else + return vm.communicate.upload(source, dest_file) + end + end + end + + + private + + def compress(source, source_is_dir) + require 'zlib' + require 'tempfile' + require 'archive/tar/minitar' + + cwd = Dir.pwd + begin + tmp = ::Tempfile.new(['script', '.tar.gz']) + tmp.binmode + tgz = Zlib::GzipWriter.new (tmp) + + Dir.chdir source_is_dir ? source : ::File.dirname(source) + Archive::Tar::Minitar.pack(source_is_dir ? '.' : ::File.basename(source), tgz) + + tmp.path # returns the temporary file path + ensure + tgz.close if tgz && !tgz.closed? + tmp.close if tmp && !tmp.closed? + Dir.chdir cwd + end + end + + def parse_args(options) opts = OptionParser.new do |o| o.banner = <<-EOS Usage: -\tvagrant winrm-upload [name] -\tvagrant winrm-upload -t [name] +\tvagrant winrm-upload [-c] [name] +\tvagrant winrm-upload [-c] -t [name] EOS o.separator 'Options:' o.on('-t', '--temporary', 'Upload the source file to a temporary directory and return the path') do options[:temporary] = true end + + o.on('-c', '--compress', 'Use gzip compression to speed up the upload') do + options[:compress] = true + end end # Parse the options and return if we don't have any target. @@ -37,24 +95,9 @@ def execute if argv.empty? || argv.length > max || argv.length < min raise Vagrant::Errors::CLIInvalidUsage, help: opts.help.chomp end - argv = argv.drop(min) - - # Execute the actual WinRM - with_target_vms(argv, single_target: true) do |vm| - - raise Errors::ConfigurationError, { :communicator => vm.config.vm.communicator } if vm.config.vm.communicator != :winrm - - destination_file = options[:temporary] ? ::File.join(get_remote_temp_folder(vm), destination) : destination - $stdout.print destination_file if options[:temporary] - - @logger.debug("Uploading #{source} to #{destination}") - return vm.communicate.upload(source, destination_file) - end + [source, destination, argv.drop(min)] end - - private - def get_remote_temp_folder(vm) dir = nil vm.communicate.execute('[System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName()) | Write-Host -NoNewline') do |type, data| diff --git a/lib/version.rb b/lib/version.rb index b34ead4..d6f34bf 100644 --- a/lib/version.rb +++ b/lib/version.rb @@ -1,5 +1,5 @@ module VagrantPlugins module VagrantWinRM - VERSION = '0.2.0' + VERSION = '0.4.0' end end diff --git a/vagrant-winrm.gemspec b/vagrant-winrm.gemspec index 3a237c1..a25dbee 100644 --- a/vagrant-winrm.gemspec +++ b/vagrant-winrm.gemspec @@ -14,13 +14,15 @@ Gem::Specification.new do |s| s.required_rubygems_version = '>= 2.0.0' + s.add_dependency 'minitar', '~> 0.5' + s.add_development_dependency 'rake' s.add_development_dependency 'rspec_junit_formatter' - s.add_development_dependency 'rspec-core', '~> 3.0.0' - s.add_development_dependency 'rspec-expectations', '~> 3.0.0' - s.add_development_dependency 'rspec-mocks', '~> 3.0.0' + s.add_development_dependency 'rspec-core', '~> 3.0' + s.add_development_dependency 'rspec-expectations', '~> 3.0' + s.add_development_dependency 'rspec-mocks', '~> 3.0' - s.add_development_dependency 'bundler', '>= 1.0.0' + s.add_development_dependency 'bundler', '~> 1.0' s.files = `git ls-files`.split("\n") s.executables = `git ls-files`.split("\n").map { |f| f =~ /^bin\/(.*)/ ? $1 : nil }.compact