[关闭]
@qidiandasheng 2022-01-05T15:36:13.000000Z 字数 3720 阅读 937

Cocoapods核心组件:cocoapods-downloader

Cocoapods


介绍

Cocoapods-Downloader 是用于下载源码的小工具,它支持各种类型的版本管理工具,包括 HTTP / SVN / Git / Mercurial。它可以提供tagscommitesrevisionsbranches以及zips文件的下载和解压缩操作。

文件构成

我们先通过入口文件 lib/cocoapods-downloader.rb 来一窥cocoapods-downloader项目的主要文件:

  1. module Pod
  2. module Downloader
  3. require 'cocoapods-downloader/gem_version'
  4. require 'cocoapods-downloader/api'
  5. require 'cocoapods-downloader/api_exposable'
  6. require 'cocoapods-downloader/base'
  7. # 下载方式
  8. autoload :Bazaar, 'cocoapods-downloader/bazaar'
  9. autoload :Git, 'cocoapods-downloader/git'
  10. autoload :Http, 'cocoapods-downloader/http'
  11. autoload :Mercurial, 'cocoapods-downloader/mercurial'
  12. autoload :Scp, 'cocoapods-downloader/scp'
  13. # 下载方式对于的版本,比如tag等
  14. autoload :Subversion, 'cocoapods-downloader/subversion'
  15. # 支持的下载方式
  16. def self.downloader_class_by_key
  17. {
  18. :bzr => Bazaar,
  19. :git => Git,
  20. :hg => Mercurial,
  21. :http => Http,
  22. :scp => Scp,
  23. :svn => Subversion,
  24. }
  25. end
  26. end

下载流程

查找缓存

  1. # lib/cocoapods/downloader/cache.rb
  2. def download_pod(request)
  3. # 如果缓存中不存在,则进入无缓存下载
  4. cached_pod(request) || uncached_pod(request)
  5. rescue Informative
  6. raise
  7. rescue
  8. UI.puts("\n[!] Error installing #{request.name}".red)
  9. raise
  10. end
  11. # requeset对象包括podname,git地址和tag,以及spec对象
  12. def uncached_pod(request)
  13. in_tmpdir do |target|
  14. # 下载完成之后会返回一个result(response),和对应的podspec对象
  15. result, podspecs = download(request, target)
  16. result.location = nil
  17. podspecs.each do |name, spec|
  18. # 获取对应pod的缓存路径
  19. destination = path_for_pod(request, :name => name, :params => result.checkout_options)
  20. # 从下载目录复制到缓存目录中
  21. copy_and_clean(target, destination, spec)
  22. # podspec转成json类型存入缓存中
  23. write_spec(spec, path_for_spec(request, :name => name, :params => result.checkout_options))
  24. if request.name == name
  25. result.location = destination
  26. end
  27. end
  28. result
  29. end
  30. end
  31. # 准备下载
  32. def download(request, target)
  33. Downloader.download_request(request, target)
  34. end

初始化Downloader对象

  1. # lib/cocoapods/downloader.rb
  2. def self.download_request(request, target)
  3. result = Response.new
  4. result.checkout_options = download_source(target, request.params)
  5. result.location = target
  6. if request.released_pod?
  7. result.spec = request.spec
  8. podspecs = { request.name => request.spec }
  9. else
  10. podspecs = Sandbox::PodspecFinder.new(target).podspecs
  11. podspecs[request.name] = request.spec if request.spec
  12. podspecs.each do |name, spec|
  13. if request.name == name
  14. result.spec = spec
  15. end
  16. end
  17. end
  18. [result, podspecs]
  19. end
  20. # target是下载目录,params存的是git地址和tag
  21. def self.download_source(target, params)
  22. FileUtils.rm_rf(target)
  23. # 根据目录和下载地址生成Downloader对象
  24. downloader = Downloader.for_target(target, params)
  25. downloader.download
  26. target.mkpath
  27. if downloader.options_specific?
  28. params
  29. else
  30. downloader.checkout_options
  31. end
  32. end

Downloader对象开始下载

根据对应的下载类型,会生成对应的下载类型的对象:

  1. def self.for_target(target_path, options)
  2. options = options_to_sym(options)
  3. if target_path.nil?
  4. raise DownloaderError, 'No target path provided.'
  5. end
  6. # 这里的options为{git:'',tag:''},下载类型为git,则这里生成的klass为Pod::Downloader::Git
  7. strategy, klass = class_for_options(options)
  8. url = options[strategy]
  9. sub_options = options.dup
  10. sub_options.delete(strategy)
  11. # Pod::Downloader::Git类初始化
  12. klass.new(target_path, url, sub_options)
  13. end

下载类型gitmercurialremote_filebazaar等的基类是base,初始化方法会走入基类里面:

  1. # lib/cocoapods-downloader/base.rb
  2. # 初始化对象,保存url,options,创建下载目录
  3. def initialize(target_path, url, options)
  4. require 'pathname'
  5. @target_path = Pathname.new(target_path)
  6. @url = url
  7. @options = options
  8. unrecognized_options = options.keys - self.class.options
  9. unless unrecognized_options.empty?
  10. raise DownloaderError, "Unrecognized options `#{unrecognized_options}`"
  11. end
  12. end
  13. # name就是对应的子类的class名
  14. def download
  15. ui_action("#{name} download") do
  16. target_path.mkpath
  17. download!
  18. end
  19. end

最后进入子类的执行下载的函数:

  1. # lib/cocoapods-downloader/git.rb
  2. module Pod
  3. module Downloader
  4. class Git < Base
  5. def download!
  6. clone
  7. checkout_commit if options[:commit]
  8. end
  9. def clone(force_head = false, shallow_clone = true)
  10. ui_sub_action('Git download') do
  11. begin
  12. git! clone_arguments(force_head, shallow_clone)
  13. update_submodules
  14. rescue DownloaderError => e
  15. if e.message =~ /^fatal:.*does not support (--depth|shallow capabilities)$/im
  16. clone(force_head, false)
  17. else
  18. raise
  19. end
  20. end
  21. end
  22. end
  23. .
  24. .
  25. .
  26. end
  27. end
  28. end
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注