From 76345711c401345f6ba4b63b0ddb16fce8670e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eloy=20Dur=C3=A1n?= Date: Sat, 21 Jul 2012 17:14:15 +0200 Subject: [PATCH] Clean pods *after* resolving and activating. Fixes #414. --- Gemfile | 2 +- Gemfile.lock | 4 ++-- lib/cocoapods/dependency.rb | 24 +++++++++++++++--------- lib/cocoapods/installer.rb | 24 ++++++++++++------------ lib/cocoapods/local_pod.rb | 13 ++++++++++--- lib/cocoapods/sandbox.rb | 21 +++++++++++++++------ spec/unit/dependency_spec.rb | 14 ++++++++++++++ spec/unit/sandbox_spec.rb | 34 ++++++++++++++++++++++++++++++++++ 8 files changed, 103 insertions(+), 33 deletions(-) diff --git a/Gemfile b/Gemfile index 633359e6eb..6c5c9bef1e 100644 --- a/Gemfile +++ b/Gemfile @@ -7,7 +7,7 @@ group :development do gem "mocha", "~> 0.11.4" gem "bacon" - gem "kicker" + gem "kicker", "~> 3.0.0pre1" gem "mocha-on-bacon" gem "rake" gem "rb-fsevent" diff --git a/Gemfile.lock b/Gemfile.lock index 5fa28ca185..2517b920ef 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -41,7 +41,7 @@ GEM hashie (1.2.0) i18n (0.6.0) json (1.7.3) - kicker (2.6.1) + kicker (3.0.0pre1) listen listen (0.4.7) rb-fchange (~> 0.0.5) @@ -88,7 +88,7 @@ DEPENDENCIES bacon cocoapods! github-markup - kicker + kicker (~> 3.0.0pre1) mocha (~> 0.11.4) mocha-on-bacon pry diff --git a/lib/cocoapods/dependency.rb b/lib/cocoapods/dependency.rb index 833223ab57..932d3d5e79 100644 --- a/lib/cocoapods/dependency.rb +++ b/lib/cocoapods/dependency.rb @@ -146,16 +146,20 @@ def initialize(name, params) end def specification_from_sandbox(sandbox, platform) + specification_from_local(sandbox, platform) || specification_from_external(sandbox, platform) + end + + def specification_from_local(sandbox, platform) if local_pod = sandbox.installed_pod_named(name, platform) local_pod.top_specification - else - copy_external_source_into_sandbox(sandbox) - local_pod = sandbox.installed_pod_named(name, platform) - local_pod.clean if config.clean? && local_pod.exists? - local_pod.top_specification end end + def specification_from_external(sandbox, platform) + copy_external_source_into_sandbox(sandbox, platform) + specification_from_local(sandbox, platform) + end + def ==(other_source) return if other_source.nil? name == other_source.name && params == other_source.params @@ -163,10 +167,12 @@ def ==(other_source) end class GitSource < AbstractExternalSource - def copy_external_source_into_sandbox(sandbox) + def copy_external_source_into_sandbox(sandbox, platform) puts " * Pre-downloading: '#{name}'" unless config.silent? - Downloader.for_target(sandbox.root + name, @params).tap do |downloader| - downloader.download + downloader = Downloader.for_target(sandbox.root + name, @params) + downloader.download + if local_pod = sandbox.installed_pod_named(name, platform) + local_pod.downloaded = true end end @@ -181,7 +187,7 @@ def description # can be http, file, etc class PodspecSource < AbstractExternalSource - def copy_external_source_into_sandbox(sandbox) + def copy_external_source_into_sandbox(sandbox, _) output_path = sandbox.root + "Local Podspecs/#{name}.podspec" output_path.dirname.mkpath puts " * Fetching podspec for `#{name}' from: #{@params[:podspec]}" unless config.silent? diff --git a/lib/cocoapods/installer.rb b/lib/cocoapods/installer.rb index 96e2223590..1c2d2dc9df 100644 --- a/lib/cocoapods/installer.rb +++ b/lib/cocoapods/installer.rb @@ -57,12 +57,17 @@ def install_dependencies! puts marker << ( pod.exists? ? "Using #{name}" : "Installing #{name}".green ) end - unless pod.exists? - download_pod(pod) - # The docs need to be generated before cleaning because - # the documentation is created for all the subspecs. + download_pod(pod) unless pod.exists? + + # This will not happen if the pod existed before we started the install + # process. + if pod.downloaded? + # The docs need to be generated before cleaning because the + # documentation is created for all the subspecs. generate_docs(pod) - pod.clean if config.clean + # Here we clean pod's that just have been downloaded or have been + # pre-downloaded in AbstractExternalSource#specification_from_sandbox. + pod.clean! if config.clean? end end end @@ -79,6 +84,7 @@ def download_pod(pod) else downloader.download end + pod.downloaded = true end #TODO: move to generator ? @@ -207,18 +213,12 @@ def pods_by_target specs_by_target.each do |target_definition, specs| @pods_by_spec[target_definition.platform] = {} result[target_definition] = specs.map do |spec| - pod = pod_for_spec(spec, target_definition.platform) - pod.add_specification(spec) - pod + @sandbox.local_pod_for_spec(spec, target_definition.platform) end.uniq.compact end result end - def pod_for_spec(spec, platform) - @pods_by_spec[platform][spec.top_level_parent.name] ||= LocalPod.new(spec, @sandbox, platform) - end - private def print_title(title, only_verbose = true) diff --git a/lib/cocoapods/local_pod.rb b/lib/cocoapods/local_pod.rb index ce0c207178..22ddedf932 100644 --- a/lib/cocoapods/local_pod.rb +++ b/lib/cocoapods/local_pod.rb @@ -38,6 +38,13 @@ class LocalPod # attr_reader :platform + # @return [Boolean] Wether or not the pod has been downloaded in the + # current install process and still needs its docs + # generated and be cleaned. + # + attr_accessor :downloaded + alias_method :downloaded?, :downloaded + # @param [Specification] specification # The first activated specification of the pod. # @param [Sandbox] sandbox @@ -139,7 +146,7 @@ def implode # # @return [void] # - def clean + def clean! clean_paths.each { |path| FileUtils.rm_rf(path) } @cleaned = true end @@ -299,8 +306,8 @@ def xcconfig # def all_specs_public_header_files if @cleaned - raise Informative, "The pod is cleaned and cannot compute the all the "\ - "header files as they might be deleted." + raise Informative, "The pod is cleaned and cannot compute the " \ + "header files, as some might have been deleted." end all_specs = [ top_specification ] + top_specification.subspecs diff --git a/lib/cocoapods/sandbox.rb b/lib/cocoapods/sandbox.rb index ae2f8f9fd0..3820149a93 100644 --- a/lib/cocoapods/sandbox.rb +++ b/lib/cocoapods/sandbox.rb @@ -9,6 +9,7 @@ class Sandbox def initialize(path) @root = Pathname.new(path) @header_search_paths = [HEADERS_DIR] + @cached_local_pods = {} FileUtils.mkdir_p(@root) end @@ -56,17 +57,25 @@ def prepare_for_install headers_root.rmtree if headers_root.exist? end - def podspec_for_name(name) - if spec_path = Dir[root + "#{name}/*.podspec"].first - Pathname.new(spec_path) - elsif spec_path = Dir[root + "Local Podspecs/#{name}.podspec"].first - Pathname.new(spec_path) + def local_pod_for_spec(spec, platform) + key = [spec.top_level_parent.name, platform.to_sym] + (@cached_local_pods[key] ||= LocalPod.new(spec.top_level_parent, self, platform)).tap do |pod| + pod.add_specification(spec) end end def installed_pod_named(name, platform) if spec_path = podspec_for_name(name) - LocalPod.from_podspec(spec_path, self, platform) + key = [name, platform.to_sym] + @cached_local_pods[key] ||= LocalPod.from_podspec(spec_path, self, platform) + end + end + + def podspec_for_name(name) + if spec_path = Dir[root + "#{name}/*.podspec"].first + Pathname.new(spec_path) + elsif spec_path = Dir[root + "Local Podspecs/#{name}.podspec"].first + Pathname.new(spec_path) end end end diff --git a/spec/unit/dependency_spec.rb b/spec/unit/dependency_spec.rb index 25952491d0..b4b806b648 100644 --- a/spec/unit/dependency_spec.rb +++ b/spec/unit/dependency_spec.rb @@ -88,5 +88,19 @@ module Pod end end end + + describe Dependency::ExternalSources::GitSource do + before do + @dependency = Dependency.new("cocoapods", :git => "git://github.com/cocoapods/cocoapods") + end + + it "marks a LocalPod as downloaded if it's downloaded" do + Downloader.stubs(:for_target).returns(stub_everything) + + pod = mock('LocaPod', :downloaded= => true) + sandbox = stub('Sandbox', :root => '', :installed_pod_named => pod) + @dependency.external_source.copy_external_source_into_sandbox(sandbox, Platform.ios) + end + end end end diff --git a/spec/unit/sandbox_spec.rb b/spec/unit/sandbox_spec.rb index 77f9fb1708..f71dd4391a 100644 --- a/spec/unit/sandbox_spec.rb +++ b/spec/unit/sandbox_spec.rb @@ -76,4 +76,38 @@ @sandbox.prepare_for_install @sandbox.headers_root.should.not.exist end + + it "returns the path to a spec file in the root of the pod's dir" do + FileUtils.cp_r(fixture('banana-lib'), @sandbox.root + 'BananaLib') + @sandbox.podspec_for_name('BananaLib').should == @sandbox.root + 'BananaLib/BananaLib.podspec' + end + + it "returns the path to a spec file in the 'Local Podspecs' dir" do + (@sandbox.root + 'Local Podspecs').mkdir + FileUtils.cp(fixture('banana-lib') + 'BananaLib.podspec', @sandbox.root + 'Local Podspecs') + @sandbox.podspec_for_name('BananaLib').should == @sandbox.root + 'Local Podspecs/BananaLib.podspec' + end + + it "returns a LocalPod for a spec file in the sandbox" do + FileUtils.cp_r(fixture('banana-lib'), @sandbox.root + 'BananaLib') + pod = @sandbox.installed_pod_named('BananaLib', Pod::Platform.ios) + pod.should.be.instance_of Pod::LocalPod + pod.top_specification.name.should == 'BananaLib' + end + + it "returns a LocalPod for a spec instance which source is expected to be in the sandbox" do + spec = Pod::Specification.from_file(fixture('banana-lib') + 'BananaLib.podspec') + pod = @sandbox.local_pod_for_spec(spec, Pod::Platform.ios) + pod.should.be.instance_of Pod::LocalPod + pod.top_specification.name.should == 'BananaLib' + end + + it "always returns the same cached LocalPod instance for the same spec and platform" do + FileUtils.cp_r(fixture('banana-lib'), @sandbox.root + 'BananaLib') + spec = Pod::Specification.from_file(@sandbox.root + 'BananaLib/BananaLib.podspec') + + pod = @sandbox.installed_pod_named('BananaLib', Pod::Platform.ios) + @sandbox.installed_pod_named('BananaLib', Pod::Platform.ios).should.eql pod + @sandbox.local_pod_for_spec(spec, Pod::Platform.ios).should.eql pod + end end