@qidiandasheng
        
        2022-01-05T07:36:13.000000Z
        字数 3720
        阅读 1378
    Cocoapods
Cocoapods-Downloader 是用于下载源码的小工具,它支持各种类型的版本管理工具,包括 HTTP / SVN / Git / Mercurial。它可以提供tags、commites,revisions,branches以及zips文件的下载和解压缩操作。
我们先通过入口文件 lib/cocoapods-downloader.rb 来一窥cocoapods-downloader项目的主要文件:
module Podmodule Downloaderrequire 'cocoapods-downloader/gem_version'require 'cocoapods-downloader/api'require 'cocoapods-downloader/api_exposable'require 'cocoapods-downloader/base'# 下载方式autoload :Bazaar, 'cocoapods-downloader/bazaar'autoload :Git, 'cocoapods-downloader/git'autoload :Http, 'cocoapods-downloader/http'autoload :Mercurial, 'cocoapods-downloader/mercurial'autoload :Scp, 'cocoapods-downloader/scp'# 下载方式对于的版本,比如tag等autoload :Subversion, 'cocoapods-downloader/subversion'# 支持的下载方式def self.downloader_class_by_key{:bzr => Bazaar,:git => Git,:hg => Mercurial,:http => Http,:scp => Scp,:svn => Subversion,}endend
# lib/cocoapods/downloader/cache.rbdef download_pod(request)# 如果缓存中不存在,则进入无缓存下载cached_pod(request) || uncached_pod(request)rescue InformativeraiserescueUI.puts("\n[!] Error installing #{request.name}".red)raiseend# requeset对象包括podname,git地址和tag,以及spec对象def uncached_pod(request)in_tmpdir do |target|# 下载完成之后会返回一个result(response),和对应的podspec对象result, podspecs = download(request, target)result.location = nilpodspecs.each do |name, spec|# 获取对应pod的缓存路径destination = path_for_pod(request, :name => name, :params => result.checkout_options)# 从下载目录复制到缓存目录中copy_and_clean(target, destination, spec)# podspec转成json类型存入缓存中write_spec(spec, path_for_spec(request, :name => name, :params => result.checkout_options))if request.name == nameresult.location = destinationendendresultendend# 准备下载def download(request, target)Downloader.download_request(request, target)end
# lib/cocoapods/downloader.rbdef self.download_request(request, target)result = Response.newresult.checkout_options = download_source(target, request.params)result.location = targetif request.released_pod?result.spec = request.specpodspecs = { request.name => request.spec }elsepodspecs = Sandbox::PodspecFinder.new(target).podspecspodspecs[request.name] = request.spec if request.specpodspecs.each do |name, spec|if request.name == nameresult.spec = specendendend[result, podspecs]end# target是下载目录,params存的是git地址和tagdef self.download_source(target, params)FileUtils.rm_rf(target)# 根据目录和下载地址生成Downloader对象downloader = Downloader.for_target(target, params)downloader.downloadtarget.mkpathif downloader.options_specific?paramselsedownloader.checkout_optionsendend
根据对应的下载类型,会生成对应的下载类型的对象:
def self.for_target(target_path, options)options = options_to_sym(options)if target_path.nil?raise DownloaderError, 'No target path provided.'end# 这里的options为{git:'',tag:''},下载类型为git,则这里生成的klass为Pod::Downloader::Gitstrategy, klass = class_for_options(options)url = options[strategy]sub_options = options.dupsub_options.delete(strategy)# Pod::Downloader::Git类初始化klass.new(target_path, url, sub_options)end
下载类型git、mercurial、remote_file、bazaar等的基类是base,初始化方法会走入基类里面:
# lib/cocoapods-downloader/base.rb# 初始化对象,保存url,options,创建下载目录def initialize(target_path, url, options)require 'pathname'@target_path = Pathname.new(target_path)@url = url@options = optionsunrecognized_options = options.keys - self.class.optionsunless unrecognized_options.empty?raise DownloaderError, "Unrecognized options `#{unrecognized_options}`"endend# name就是对应的子类的class名def downloadui_action("#{name} download") dotarget_path.mkpathdownload!endend
最后进入子类的执行下载的函数:
# lib/cocoapods-downloader/git.rbmodule Podmodule Downloaderclass Git < Basedef download!clonecheckout_commit if options[:commit]enddef clone(force_head = false, shallow_clone = true)ui_sub_action('Git download') dobegingit! clone_arguments(force_head, shallow_clone)update_submodulesrescue DownloaderError => eif e.message =~ /^fatal:.*does not support (--depth|shallow capabilities)$/imclone(force_head, false)elseraiseendendendend...endendend