diff --git a/lib/cocoapods-downloader/base.rb b/lib/cocoapods-downloader/base.rb index 131f5c3..3d20fc8 100644 --- a/lib/cocoapods-downloader/base.rb +++ b/lib/cocoapods-downloader/base.rb @@ -63,6 +63,10 @@ def name self.class.name.split('::').last end + def escaped_target_path + escape_pathname(target_path) + end + #-----------------------------------------------------------------------# # @!group Configuration @@ -224,6 +228,11 @@ def self.executable(name) execute_command(name.to_s, command, true) end end + + def escape_pathname(pathname=target_path) + require "shellwords" + pathname.to_s.shellescape + end end end end diff --git a/lib/cocoapods-downloader/bazaar.rb b/lib/cocoapods-downloader/bazaar.rb index 6ecf8e1..95505b3 100644 --- a/lib/cocoapods-downloader/bazaar.rb +++ b/lib/cocoapods-downloader/bazaar.rb @@ -34,11 +34,11 @@ def download! end def download_head! - bzr! %|branch "#{url}" #{dir_opts} "#{target_path}"| + bzr! %|branch "#{url}" #{dir_opts} #{escaped_target_path}| end def download_revision!(rev) - bzr! %|branch "#{url}" #{dir_opts} -r '#{rev}' "#{target_path}"| + bzr! %|branch "#{url}" #{dir_opts} -r '#{rev}' #{escaped_target_path}| end def dir_opts diff --git a/lib/cocoapods-downloader/git.rb b/lib/cocoapods-downloader/git.rb index a0d1321..7b9e21a 100644 --- a/lib/cocoapods-downloader/git.rb +++ b/lib/cocoapods-downloader/git.rb @@ -64,7 +64,7 @@ def clone_url # def clone(from, to, flags = '') ui_sub_action("Cloning to Pods folder") do - command = %Q|clone "#{from}" "#{to}"| + command = %Q|clone #{from} #{escape_pathname(to)}| command << ' ' + flags if flags git!(command) end diff --git a/lib/cocoapods-downloader/http.rb b/lib/cocoapods-downloader/http.rb index 559beb4..4d71162 100644 --- a/lib/cocoapods-downloader/http.rb +++ b/lib/cocoapods-downloader/http.rb @@ -20,7 +20,7 @@ class UnsupportedFileTypeError < StandardError; end def download! @filename = filename_with_type(type) - @download_path = target_path + @filename + @download_path = escape_pathname(target_path + @filename) download_file(@download_path) extract_with_type(@download_path, type) end @@ -84,21 +84,21 @@ def filename_with_type(type=:zip) end def download_file(full_filename) - curl! "-L -o '#{full_filename}' '#{url}'" + curl! %|-L -o #{full_filename} #{url} --create-dirs| end def extract_with_type(full_filename, type=:zip) case type when :zip - unzip! "'#{full_filename}' -d '#{target_path}'" + unzip! %|#{full_filename} -d #{escaped_target_path}| when :tgz - tar! "xfz '#{full_filename}' -C '#{target_path}'" + tar! %|xfz #{full_filename} -C #{escaped_target_path}| when :tar - tar! "xf '#{full_filename}' -C '#{target_path}'" + tar! %|xf #{full_filename} -C #{escaped_target_path}| when :tbz - tar! "xfj '#{full_filename}' -C '#{target_path}'" + tar! %|xfj #{full_filename} -C #{escaped_target_path}| when :txz - tar! "xf '#{full_filename}' -C '#{target_path}'" + tar! %|xf #{full_filename} -C #{escaped_target_path}| else raise UnsupportedFileTypeError.new "Unsupported file type: #{type}" end @@ -106,7 +106,7 @@ def extract_with_type(full_filename, type=:zip) # If the archive is a tarball and it only contained a folder, move its contents to the target (#727) if should_flatten? contents = target_path.children - contents.delete(full_filename) + contents.delete(target_path + @filename) entry = contents.first if contents.count == 1 && entry.directory? FileUtils.move(entry.children, target_path) diff --git a/lib/cocoapods-downloader/mercurial.rb b/lib/cocoapods-downloader/mercurial.rb index 57f7a88..049acb6 100644 --- a/lib/cocoapods-downloader/mercurial.rb +++ b/lib/cocoapods-downloader/mercurial.rb @@ -32,11 +32,11 @@ def download! end def download_head! - hg! %|clone "#{url}" "#{target_path}"| + hg! %|clone #{url} #{escaped_target_path}| end def download_revision! - hg! %|clone "#{url}" --rev '#{options[:revision]}' "#{target_path}"| + hg! %|clone "#{url}" --rev '#{options[:revision]}' #{escaped_target_path}| end end diff --git a/lib/cocoapods-downloader/subversion.rb b/lib/cocoapods-downloader/subversion.rb index 050443b..f440101 100644 --- a/lib/cocoapods-downloader/subversion.rb +++ b/lib/cocoapods-downloader/subversion.rb @@ -23,12 +23,12 @@ def checkout_options executable :svn def download! - output = svn!(%|#{export_subcommand} "#{reference_url}" "#{target_path}"|) + output = svn!(%|#{export_subcommand} "#{reference_url}" #{escaped_target_path}|) store_exported_revision(output) end def download_head! - output = svn!(%|#{export_subcommand} "#{trunk_url}" "#{target_path}"|) + output = svn!(%|#{export_subcommand} "#{trunk_url}" #{escaped_target_path}|) store_exported_revision(output) end diff --git a/spec/cocoapods-downloaders/bazaar_spec.rb b/spec/cocoapods-downloaders/bazaar_spec.rb index 4b1f3a3..e2258b1 100644 --- a/spec/cocoapods-downloaders/bazaar_spec.rb +++ b/spec/cocoapods-downloaders/bazaar_spec.rb @@ -36,6 +36,22 @@ module Downloader tmp_folder('README').read.strip.should == 'Fourth Commit' end + describe "when the directory name has quotes or spaces" do + it 'checks out the head revision' do + options = { :bzr => fixture('bazaar-repo') } + downloader = Downloader.for_target(tmp_folder_with_quotes, options) + downloader.download + tmp_folder_with_quotes("README").read.strip.should == 'Fourth Commit' + end + + it 'checks out a specific revision into a directory with quotes' do + options = { :bzr => fixture('bazaar-repo'), :revision => '1' } + downloader = Downloader.for_target(tmp_folder_with_quotes, options) + downloader.download + tmp_folder_with_quotes("README").read.strip.should == 'First Commit' + end + end + it 'returns the checked out revision' do options = { :bzr => fixture('bazaar-repo') } downloader = Downloader.for_target(tmp_folder, options) diff --git a/spec/cocoapods-downloaders/git_spec.rb b/spec/cocoapods-downloaders/git_spec.rb index e3f71eb..444ebcd 100644 --- a/spec/cocoapods-downloaders/git_spec.rb +++ b/spec/cocoapods-downloaders/git_spec.rb @@ -15,6 +15,14 @@ module Downloader tmp_folder('README').read.strip.should == 'first commit' end + + it "checks out when the path contains quotes or spaces" do + options = { :git => fixture('git-repo'), :commit => '7ad3a6c' } + downloader = Downloader.for_target(tmp_folder_with_quotes, options) + downloader.download + tmp_folder_with_quotes("README").read.strip.should == 'first commit' + end + it "checks out a specific branch" do options = { :git => fixture('git-repo'), :branch => 'topic_branch' } downloader = Downloader.for_target(tmp_folder, options) diff --git a/spec/cocoapods-downloaders/http_spec.rb b/spec/cocoapods-downloaders/http_spec.rb index 575bf69..0b46f0b 100644 --- a/spec/cocoapods-downloaders/http_spec.rb +++ b/spec/cocoapods-downloaders/http_spec.rb @@ -16,6 +16,14 @@ module Downloader tmp_folder('GoogleAdMobSearchAdsSDK/GADSearchRequest.h').read.strip.should =~ /Google Search Ads iOS SDK/ end + it 'should download file and unzip it when the target folder name contains quotes or spaces' do + options = { :http => 'http://dl.google.com/googleadmobadssdk/googleadmobsearchadssdkios.zip' } + downloader = Downloader.for_target(tmp_folder_with_quotes, options) + VCR.use_cassette('tarballs', :record => :new_episodes) { downloader.download } + tmp_folder_with_quotes("GoogleAdMobSearchAdsSDK/GADSearchRequest.h").should.exist + tmp_folder_with_quotes("GoogleAdMobSearchAdsSDK/GADSearchRequest.h").read.strip.should =~ /Google Search Ads iOS SDK/ + end + it 'should flatten zip archives, when the spec explicitly demands it' do options = { :http => 'https://github.com/kevinoneill/Useful-Bits/archive/1.0.zip', diff --git a/spec/cocoapods-downloaders/mercurial_spec.rb b/spec/cocoapods-downloaders/mercurial_spec.rb index 1e2eaa6..5d3621c 100644 --- a/spec/cocoapods-downloaders/mercurial_spec.rb +++ b/spec/cocoapods-downloaders/mercurial_spec.rb @@ -22,6 +22,22 @@ module Downloader tmp_folder('README').read.strip.should == 'second commit' end + describe "when the directory name has quotes or spaces" do + it "checks out a specific revision" do + options = { :hg => fixture('mercurial-repo'), :revision => '46198bb3af96' } + downloader = Downloader.for_target(tmp_folder_with_quotes, options) + downloader.download + tmp_folder_with_quotes('README').read.strip.should == 'first commit' + end + + it "checks out the head revision" do + options = { :hg => fixture('mercurial-repo') } + downloader = Downloader.for_target(tmp_folder_with_quotes, options) + downloader.download + tmp_folder_with_quotes('README').read.strip.should == 'second commit' + end + end + it "returns the checked out revision" do options = { :hg => fixture('mercurial-repo') } downloader = Downloader.for_target(tmp_folder, options) diff --git a/spec/cocoapods-downloaders/subversion_spec.rb b/spec/cocoapods-downloaders/subversion_spec.rb index 98508a3..094104c 100644 --- a/spec/cocoapods-downloaders/subversion_spec.rb +++ b/spec/cocoapods-downloaders/subversion_spec.rb @@ -29,6 +29,22 @@ module Downloader tmp_folder('README').read.strip.should == 'unintersting' end + describe "when the directory name has quotes or spaces" do + it "checks out a specific revision" do + options = { :svn => "file://#{fixture('subversion-repo')}", :revision => '1' } + downloader = Downloader.for_target(tmp_folder_with_quotes, options) + downloader.download + tmp_folder_with_quotes('README').read.strip.should == 'first commit' + end + + it "checks out the head version" do + options = { :svn => "file://#{fixture('subversion-repo')}", :tag => 'tag-1' } + downloader = Downloader.for_target(tmp_folder_with_quotes, options) + downloader.download_head + tmp_folder_with_quotes('README').read.strip.should == 'unintersting' + end + end + it "returns the checked out revision" do options = { :svn => "file://#{fixture('subversion-repo')}" } downloader = Downloader.for_target(tmp_folder, options) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7d34eaf..5a35d2a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -49,6 +49,10 @@ def tmp_folder(path = '') return Pathname.pwd + 'tmp' + path end +def tmp_folder_with_quotes(path = '') + return tmp_folder File.join("a' \"b", path) +end + def fixture(path) return Pathname.pwd + 'spec/fixtures/' + path end