├── .gitignore ├── Gemfile ├── Gemfile.lock ├── LICENSE.txt ├── README.md ├── Rakefile ├── cocoapods-cache-proxy.gemspec ├── lib ├── cocoapods-cache-proxy.rb ├── cocoapods-cache-proxy │ ├── command.rb │ ├── command │ │ ├── cache_proxy.rb │ │ └── cache_proxy │ │ │ ├── add.rb │ │ │ ├── auth │ │ │ ├── add.rb │ │ │ ├── auth.rb │ │ │ ├── list.rb │ │ │ ├── remove.rb │ │ │ └── update.rb │ │ │ ├── list.rb │ │ │ ├── remove.rb │ │ │ └── update.rb │ ├── gem_version.rb │ ├── helper │ │ ├── cache_proxy_source_helper.rb │ │ └── helper.rb │ └── native │ │ ├── cache_proxy_auth.rb │ │ ├── cache_proxy_source.rb │ │ ├── config.rb │ │ ├── downloader.rb │ │ ├── installer.rb │ │ ├── native.rb │ │ ├── podfile_dsl.rb │ │ └── resolver.rb ├── cocoapods_plugin.rb └── hook.rb ├── test-project ├── CocopodsCacheProxy-Demo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── CocopodsCacheProxy-Demo.xcworkspace │ └── contents.xcworkspacedata ├── CocopodsCacheProxy-Demo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── SceneDelegate.h │ ├── SceneDelegate.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── Gemfile ├── Gemfile.lock ├── Podfile └── Podfile.lock └── test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/macos,ruby,objective-c 3 | # Edit at https://www.gitignore.io/?templates=macos,ruby,objective-c 4 | 5 | ### macOS ### 6 | # General 7 | .DS_Store 8 | .AppleDouble 9 | .LSOverride 10 | 11 | # Icon must end with two \r 12 | Icon 13 | 14 | # Thumbnails 15 | ._* 16 | 17 | # Files that might appear in the root of a volume 18 | .DocumentRevisions-V100 19 | .fseventsd 20 | .Spotlight-V100 21 | .TemporaryItems 22 | .Trashes 23 | .VolumeIcon.icns 24 | .com.apple.timemachine.donotpresent 25 | 26 | # Directories potentially created on remote AFP share 27 | .AppleDB 28 | .AppleDesktop 29 | Network Trash Folder 30 | Temporary Items 31 | .apdisk 32 | 33 | ### Objective-C ### 34 | # Xcode 35 | # 36 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 37 | 38 | ## Build generated 39 | build/ 40 | DerivedData/ 41 | 42 | 43 | ## Various settings 44 | *.pbxuser 45 | !default.pbxuser 46 | *.mode1v3 47 | !default.mode1v3 48 | *.mode2v3 49 | !default.mode2v3 50 | *.perspectivev3 51 | !default.perspectivev3 52 | xcuserdata/ 53 | 54 | ## Other 55 | *.moved-aside 56 | *.xccheckout 57 | *.xcscmblueprint 58 | 59 | ## Obj-C/Swift specific 60 | *.hmap 61 | *.ipa 62 | *.dSYM.zip 63 | *.dSYM 64 | 65 | # CocoaPods 66 | # We recommend against adding the Pods directory to your .gitignore. However 67 | # you should judge for yourself, the pros and cons are mentioned at: 68 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 69 | # Pods/ 70 | # Add this line if you want to avoid checking in source code from the Xcode workspace 71 | # *.xcworkspace 72 | 73 | # Carthage 74 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 75 | # Carthage/Checkouts 76 | # CocoaPods - Refactored to standalone file 77 | Pods/ 78 | 79 | Carthage/Build 80 | 81 | # fastlane 82 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 83 | # screenshots whenever they are needed. 84 | # For more information about the recommended setup visit: 85 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 86 | 87 | fastlane/report.xml 88 | fastlane/Preview.html 89 | fastlane/screenshots/**/*.png 90 | fastlane/test_output 91 | 92 | # Code Injection 93 | # After new code Injection tools there's a generated folder /iOSInjectionProject 94 | # https://github.com/johnno1962/injectionforxcode 95 | 96 | iOSInjectionProject/ 97 | 98 | ### Objective-C Patch ### 99 | 100 | ### Ruby ### 101 | *.gem 102 | *.rbc 103 | /.config 104 | /coverage/ 105 | /InstalledFiles 106 | /pkg/ 107 | /spec/reports/ 108 | /spec/examples.txt 109 | /test/tmp/ 110 | /test/version_tmp/ 111 | /tmp/ 112 | 113 | # Used by dotenv library to load environment variables. 114 | # .env 115 | 116 | # Ignore Byebug command history file. 117 | .byebug_history 118 | 119 | ## Specific to RubyMotion: 120 | .dat* 121 | .repl_history 122 | *.bridgesupport 123 | build-iPhoneOS/ 124 | build-iPhoneSimulator/ 125 | 126 | ## Specific to RubyMotion (use of CocoaPods): 127 | # We recommend against adding the Pods directory to your .gitignore. However 128 | # you should judge for yourself, the pros and cons are mentioned at: 129 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 130 | # vendor/Pods/ 131 | 132 | ## Documentation cache and generated files: 133 | /.yardoc/ 134 | /_yardoc/ 135 | /doc/ 136 | /rdoc/ 137 | 138 | ## Environment normalization: 139 | /.bundle/ 140 | /vendor/bundle 141 | /lib/bundler/man/ 142 | 143 | # for a library or gem, you might want to ignore these files since the code is 144 | # intended to run in multiple environments; otherwise, check them in: 145 | # Gemfile.lock 146 | # .ruby-version 147 | # .ruby-gemset 148 | 149 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 150 | .rvmrc 151 | .rakeTasks 152 | ### Ruby Patch ### 153 | # Used by RuboCop. Remote config files pulled in from inherit_from directive. 154 | # .rubocop-https?--* 155 | 156 | # End of https://www.gitignore.io/api/macos,ruby,objective-c 157 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://gems.ruby-china.com' 2 | 3 | # Specify your gem's dependencies in cocoapods-cache-proxy.gemspec 4 | gemspec 5 | 6 | group :development do 7 | gem 'cocoapods', '~> 1.11' 8 | 9 | gem 'mocha' 10 | gem 'bacon' 11 | gem 'mocha-on-bacon' 12 | gem 'prettybacon' 13 | end 14 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | cocoapods-cache-proxy (0.0.2) 5 | cocoapods 6 | cocoapods-core 7 | 8 | GEM 9 | remote: https://gems.ruby-china.com/ 10 | specs: 11 | CFPropertyList (3.0.2) 12 | activesupport (4.2.11.1) 13 | i18n (~> 0.7) 14 | minitest (~> 5.1) 15 | thread_safe (~> 0.3, >= 0.3.4) 16 | tzinfo (~> 1.1) 17 | algoliasearch (1.27.1) 18 | httpclient (~> 2.8, >= 2.8.3) 19 | json (>= 1.5.1) 20 | atomos (0.1.3) 21 | bacon (1.2.0) 22 | claide (1.0.3) 23 | cocoapods (1.8.4) 24 | activesupport (>= 4.0.2, < 5) 25 | claide (>= 1.0.2, < 2.0) 26 | cocoapods-core (= 1.8.4) 27 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 28 | cocoapods-downloader (>= 1.2.2, < 2.0) 29 | cocoapods-plugins (>= 1.0.0, < 2.0) 30 | cocoapods-search (>= 1.0.0, < 2.0) 31 | cocoapods-stats (>= 1.0.0, < 2.0) 32 | cocoapods-trunk (>= 1.4.0, < 2.0) 33 | cocoapods-try (>= 1.1.0, < 2.0) 34 | colored2 (~> 3.1) 35 | escape (~> 0.0.4) 36 | fourflusher (>= 2.3.0, < 3.0) 37 | gh_inspector (~> 1.0) 38 | molinillo (~> 0.6.6) 39 | nap (~> 1.0) 40 | ruby-macho (~> 1.4) 41 | xcodeproj (>= 1.11.1, < 2.0) 42 | cocoapods-core (1.8.4) 43 | activesupport (>= 4.0.2, < 6) 44 | algoliasearch (~> 1.0) 45 | concurrent-ruby (~> 1.1) 46 | fuzzy_match (~> 2.0.4) 47 | nap (~> 1.0) 48 | cocoapods-deintegrate (1.0.4) 49 | cocoapods-downloader (1.3.0) 50 | cocoapods-plugins (1.0.0) 51 | nap 52 | cocoapods-search (1.0.0) 53 | cocoapods-stats (1.1.0) 54 | cocoapods-trunk (1.4.1) 55 | nap (>= 0.8, < 2.0) 56 | netrc (~> 0.11) 57 | cocoapods-try (1.1.0) 58 | colored2 (3.1.2) 59 | concurrent-ruby (1.1.5) 60 | escape (0.0.4) 61 | fourflusher (2.3.1) 62 | fuzzy_match (2.0.4) 63 | gh_inspector (1.1.3) 64 | httpclient (2.8.3) 65 | i18n (0.9.5) 66 | concurrent-ruby (~> 1.0) 67 | json (2.3.0) 68 | minitest (5.13.0) 69 | mocha (1.11.2) 70 | mocha-on-bacon (0.2.3) 71 | mocha (>= 0.13.0) 72 | molinillo (0.6.6) 73 | nanaimo (0.2.6) 74 | nap (1.1.0) 75 | netrc (0.11.0) 76 | prettybacon (0.0.2) 77 | bacon (~> 1.2) 78 | rake (13.0.1) 79 | ruby-macho (1.4.0) 80 | thread_safe (0.3.6) 81 | tzinfo (1.2.6) 82 | thread_safe (~> 0.1) 83 | xcodeproj (1.14.0) 84 | CFPropertyList (>= 2.3.3, < 4.0) 85 | atomos (~> 0.1.3) 86 | claide (>= 1.0.2, < 2.0) 87 | colored2 (~> 3.1) 88 | nanaimo (~> 0.2.6) 89 | 90 | PLATFORMS 91 | ruby 92 | 93 | DEPENDENCIES 94 | bacon 95 | bundler 96 | cocoapods 97 | cocoapods-cache-proxy! 98 | mocha 99 | mocha-on-bacon 100 | prettybacon 101 | rake 102 | 103 | BUNDLED WITH 104 | 2.1.4 105 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 0x1306a94 <0x1306a94@gmail.com> 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cocoapods-cache-proxy 2 | 3 | pod依赖私服缓存服务, [服务端](https://github.com/0x1306a94/cocoapods-cache-proxy-server), 目前仅支持依赖库的源是 `git + tag` 方式 4 | 5 | 6 | ## Installation 7 | 8 | ```shell 9 | $ gem install cocoapods-cache-proxy 10 | ``` 11 | 12 | ## Usage 13 | 14 | ```shell 15 | $ pod cache proxy add NAME http://domain/cocoapods/proxy/repos # USER PASSWORD (USER PASSWORD 为 http basic auth user and password) 16 | ``` 17 | 18 | ## Private library authorization configuration 19 | 20 | ```shell 21 | $ pod cache proxy auth add DOMAIN TOKEN 22 | ``` 23 | 24 | * GitHub Sample 25 | * open https://github.com/settings/tokens 26 | * click `Generated new token` 27 | * Check the repo 28 | ![](https://tva1.sinaimg.cn/large/006tNbRwgy1gayhfuoxurj319w0quaek.jpg) 29 | 30 | ## Edit Podfile 31 | 32 | ```ruby 33 | plugin "cocoapods-cache-proxy", :proxy => "NAME" NAME 是 pod cache proxy add 命令中的 NAME 34 | 35 | # 忽略某个依赖,走默认处理 36 | ignore_cache_proxy_pods! ["SDWebImage"] 37 | 38 | target 'CocopodsCacheProxy-Demo' do 39 | # Comment the next line if you don't want to use dynamic frameworks 40 | use_frameworks! 41 | 42 | pod 'AFNetworking', :ignore_cache_proxy => true # 忽略代理,走默认处理 43 | pod 'SDWebImage', :cache_proxy_source => 'NAME' # NAME 是 pod cache proxy add 命令中的 NAME, 指定此依赖使用哪个代理 44 | # 此方式会走默认处理方式 45 | # http源方式会走默认处理方式 46 | pod 'QMUIKit', :git => 'https://github.com/Tencent/QMUI_iOS' 47 | # Pods for CocopodsCacheProxy-Demo 48 | 49 | end 50 | 51 | ``` 52 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | 3 | def specs(dir) 4 | FileList["spec/#{dir}/*_spec.rb"].shuffle.join(' ') 5 | end 6 | 7 | desc 'Runs all the specs' 8 | task :specs do 9 | sh "bundle exec bacon #{specs('**')}" 10 | end 11 | 12 | task :default => :specs 13 | 14 | -------------------------------------------------------------------------------- /cocoapods-cache-proxy.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'cocoapods-cache-proxy/gem_version.rb' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = 'cocoapods-cache-proxy' 8 | spec.version = CocoapodsCacheProxy::VERSION 9 | spec.authors = ['0x1306a94'] 10 | spec.email = ['0x1306a94@gmail.com'] 11 | spec.description = %q{Pod library source file cache proxy} 12 | spec.summary = %q{Pod library source file cache proxy} 13 | spec.homepage = 'https://github.com/0x1306a94/cocoapods-cache-proxy' 14 | spec.license = 'MIT' 15 | 16 | # spec.files = `git ls-files`.split($/) 17 | spec.files = Dir['lib/**/*.rb'] 18 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 19 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 20 | spec.require_paths = ['lib'] 21 | 22 | spec.add_dependency 'cocoapods', '~> 1.11' 23 | 24 | spec.add_development_dependency 'bundler', '~> 1.3' 25 | spec.add_development_dependency 'rake', '~> 12.0' 26 | end 27 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/gem_version' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/command.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/command/cache_proxy' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/command/cache_proxy.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/gem_version' 2 | 3 | module Pod 4 | class Command 5 | class Cache < Command 6 | class Proxy < Cache 7 | 8 | require 'cocoapods-cache-proxy/command/cache_proxy/add' 9 | require 'cocoapods-cache-proxy/command/cache_proxy/update' 10 | require 'cocoapods-cache-proxy/command/cache_proxy/remove' 11 | require 'cocoapods-cache-proxy/command/cache_proxy/list' 12 | 13 | require 'cocoapods-cache-proxy/command/cache_proxy/auth/auth' 14 | 15 | self.abstract_command = true 16 | self.version = CocoapodsCacheProxy::VERSION 17 | self.description = '缓存代理服务'\ 18 | "\n v#{CocoapodsCacheProxy::VERSION}\n" 19 | self.summary = <<-SUMMARY 20 | 缓存代理服务 21 | SUMMARY 22 | 23 | self.default_subcommand = 'list' 24 | 25 | def init 26 | 27 | end 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/command/cache_proxy/add.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/helper/helper' 2 | 3 | module Pod 4 | class Command 5 | class Cache < Command 6 | class Proxy < Cache 7 | class Add < Proxy 8 | self.summary = '添加缓存代理' 9 | 10 | self.description = <<-DESC 11 | 添加缓存代理 12 | DESC 13 | 14 | self.arguments = [ 15 | CLAide::Argument.new('NAME', true), 16 | CLAide::Argument.new('URL', true), 17 | CLAide::Argument.new('USER', true), 18 | CLAide::Argument.new('PASSWORD', true) 19 | ] 20 | 21 | def initialize(argv) 22 | init 23 | @name, @url, @user, @password = argv.shift_argument, argv.shift_argument, argv.shift_argument, argv.shift_argument 24 | @silent = argv.flag?('silent', false) 25 | super 26 | end 27 | 28 | def validate! 29 | super 30 | help! 'This command requires both a repo name.' unless @name 31 | help! 'This command requires both a repo url.' unless @url 32 | help! 'This command requires both a repo user.' unless @user 33 | help! 'This command requires both a repo password.' unless @password 34 | end 35 | 36 | def run 37 | raise Pod::Informative.exception "`#{@name}` 已经存在" if CPSH.check_source_conf_exists(@name) 38 | #raise Pod::Informative.exception "官方源不存在, 请先添加官方源" unless Pod::Config.instance.sources_manager.master_repo_functional? 39 | 40 | UI.section("Add proxy server config `#{@url}` into local spec repo `#{@name}`".green) do 41 | CPSH.init_cache_proxy_source(@name, @url, @user, @password) 42 | end 43 | end 44 | end 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/command/cache_proxy/auth/add.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/helper/helper' 2 | 3 | module Pod 4 | class Command 5 | class Cache < Command 6 | class Proxy < Cache 7 | class Auth < Proxy 8 | class Add < Auth 9 | self.summary = '添加缓存代理授权配置' 10 | 11 | self.description = <<-DESC 12 | 添加缓存代理授权配置 13 | DESC 14 | 15 | self.arguments = [ 16 | CLAide::Argument.new('HOST', true), 17 | CLAide::Argument.new('TOKEN', true), 18 | ] 19 | 20 | def initialize(argv) 21 | init 22 | @host, @token = argv.shift_argument, argv.shift_argument 23 | @silent = argv.flag?('silent', false) 24 | super 25 | end 26 | 27 | def validate! 28 | super 29 | help! 'This command requires both a auth host.' unless @host 30 | help! 'This command requires both a auth token.' unless @token 31 | end 32 | 33 | def run 34 | raise Pod::Informative.exception "`#{@host}` 已经存在" if CPSH.check_auth_conf_exists(@host) 35 | 36 | UI.section("Add proxy auth config `#{@host}`".green) do 37 | CPSH.init_cache_proxy_auth(@host, @token) 38 | end 39 | end 40 | end 41 | end 42 | end 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/command/cache_proxy/auth/auth.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/gem_version' 2 | require 'cocoapods-cache-proxy/command/cache_proxy' 3 | 4 | module Pod 5 | class Command 6 | class Cache < Command 7 | class Proxy < Cache 8 | class Auth < Proxy 9 | 10 | require 'cocoapods-cache-proxy/command/cache_proxy/auth/add' 11 | require 'cocoapods-cache-proxy/command/cache_proxy/auth/update' 12 | require 'cocoapods-cache-proxy/command/cache_proxy/auth/remove' 13 | require 'cocoapods-cache-proxy/command/cache_proxy/auth/list' 14 | 15 | self.abstract_command = true 16 | self.version = CocoapodsCacheProxy::VERSION 17 | self.description = '缓存代理授权配置'\ 18 | "\n v#{CocoapodsCacheProxy::VERSION}\n" 19 | self.summary = <<-SUMMARY 20 | 缓存代理授权配置 21 | SUMMARY 22 | 23 | self.default_subcommand = 'list' 24 | 25 | def init 26 | 27 | end 28 | end 29 | end 30 | end 31 | end 32 | end -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/command/cache_proxy/auth/list.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/helper/helper' 2 | require 'cocoapods-cache-proxy/native/cache_proxy_auth' 3 | 4 | module Pod 5 | class Command 6 | class Cache < Command 7 | class Proxy < Cache 8 | class Auth < Proxy 9 | class List < Auth 10 | self.summary = '列出缓存代理授权配置' 11 | 12 | self.description = <<-DESC 13 | 列出缓存代理授权配置 14 | DESC 15 | 16 | def initialize(argv) 17 | init 18 | @silent = argv.flag?('silent', false) 19 | super 20 | end 21 | 22 | def validate! 23 | super 24 | end 25 | 26 | def run 27 | auths = CPSH.get_all_auths 28 | print_auths(auths) 29 | end 30 | 31 | def print_auth(auth) 32 | if auth.is_a?(Pod::CacheProxyAuth) 33 | UI.puts "- Host: #{auth.host}" 34 | UI.puts "- Token: #{auth.token}" 35 | end 36 | end 37 | 38 | def print_auths(auths) 39 | auths.each_with_index do |auth, index| 40 | if auth.is_a?(Pod::CacheProxyAuth) 41 | UI.title "auth config: #{index + 1}" do 42 | UI.puts "- Host: #{auth.host}" 43 | UI.puts "- Token: #{auth.token}" 44 | end 45 | end 46 | end 47 | UI.puts "\n" 48 | end 49 | end 50 | end 51 | end 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/command/cache_proxy/auth/remove.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/helper/helper' 2 | 3 | module Pod 4 | class Command 5 | class Cache < Command 6 | class Proxy < Cache 7 | class Auth < Proxy 8 | class Remove < Auth 9 | self.summary = '移除缓存代理授权配置' 10 | 11 | self.description = <<-DESC 12 | 移除缓存代理授权配置 13 | DESC 14 | 15 | self.arguments = [ 16 | CLAide::Argument.new('HOST', true), 17 | ] 18 | 19 | def initialize(argv) 20 | init 21 | @host = argv.shift_argument 22 | @silent = argv.flag?('silent', false) 23 | super 24 | end 25 | 26 | def validate! 27 | super 28 | help! 'This command requires both a auth host.' unless @host 29 | end 30 | 31 | def run 32 | raise Pod::Informative.exception "`#{@host}` 不存在" unless CPSH.check_auth_conf_exists(@host) 33 | 34 | UI.section("remove cache proxy auth `#{@host}`".green) do 35 | CPSH.remove_cache_proxy_auth(@host) 36 | end 37 | end 38 | end 39 | end 40 | end 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/command/cache_proxy/auth/update.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/helper/helper' 2 | 3 | module Pod 4 | class Command 5 | class Cache < Command 6 | class Proxy < Cache 7 | class Auth < Proxy 8 | class Update < Auth 9 | self.summary = '更新缓存代理授权配置' 10 | 11 | self.description = <<-DESC 12 | 更新缓存代理授权配置 13 | DESC 14 | 15 | self.arguments = [ 16 | CLAide::Argument.new('HOST', true), 17 | CLAide::Argument.new('TOKEN', true), 18 | ] 19 | 20 | def initialize(argv) 21 | init 22 | @host, @token = argv.shift_argument, argv.shift_argument 23 | @silent = argv.flag?('silent', false) 24 | super 25 | end 26 | 27 | def validate! 28 | super 29 | help! 'This command requires both a auth host.' unless @host 30 | help! 'This command requires both a auth token.' unless @token 31 | end 32 | 33 | def run 34 | raise Pod::Informative.exception "`#{@host}` 不存在" unless CPSH.check_auth_conf_exists(@host) 35 | 36 | UI.section("Update proxy auth config `#{@host}`".green) do 37 | CPSH.init_cache_proxy_auth(@host, @token) 38 | end 39 | end 40 | end 41 | end 42 | end 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/command/cache_proxy/list.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/helper/helper' 2 | require 'cocoapods-cache-proxy/native/cache_proxy_source' 3 | 4 | module Pod 5 | class Command 6 | class Cache < Command 7 | class Proxy < Cache 8 | class List < Proxy 9 | self.summary = '列出缓存代理' 10 | 11 | self.description = <<-DESC 12 | 列出缓存代理 13 | DESC 14 | 15 | def initialize(argv) 16 | init 17 | @silent = argv.flag?('silent', false) 18 | super 19 | end 20 | 21 | def validate! 22 | super 23 | end 24 | 25 | def run 26 | sources = CPSH.get_all_sources 27 | print_sources(sources) 28 | end 29 | 30 | def print_source(source) 31 | if source.is_a?(Pod::CacheProxySource) 32 | UI.puts "- URL: #{source.baseURL}" 33 | UI.puts "- Path: #{CPSH.get_source_root_dir(source.name)}" 34 | end 35 | end 36 | 37 | def print_sources(sources) 38 | sources.each do |source| 39 | if source.is_a?(Pod::CacheProxySource) 40 | UI.title source.name do 41 | UI.puts "- URL: #{source.baseURL}" 42 | UI.puts "- Path: #{CPSH.get_source_root_dir(source.name)}" 43 | end 44 | end 45 | end 46 | UI.puts "\n" 47 | end 48 | end 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/command/cache_proxy/remove.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/helper/helper' 2 | 3 | module Pod 4 | class Command 5 | class Cache < Command 6 | class Proxy < Cache 7 | class Remove < Proxy 8 | self.summary = '移除缓存代理' 9 | 10 | self.description = <<-DESC 11 | 移除缓存代理 12 | DESC 13 | 14 | self.arguments = [ 15 | CLAide::Argument.new('NAME', true), 16 | ] 17 | 18 | def initialize(argv) 19 | init 20 | @name = argv.shift_argument 21 | @silent = argv.flag?('silent', false) 22 | super 23 | end 24 | 25 | def validate! 26 | super 27 | help! 'This command requires both a repo name.' unless @name 28 | end 29 | 30 | def run 31 | raise Pod::Informative.exception "`#{@name}` 不存在" unless CPSH.check_source_conf_exists(@name) 32 | 33 | UI.section("Remove cache proxy repo `#{@name}`".green) do 34 | CPSH.remove_cache_proxy_source(@name) 35 | end 36 | end 37 | end 38 | end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/command/cache_proxy/update.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/helper/helper' 2 | 3 | module Pod 4 | class Command 5 | class Cache < Command 6 | class Proxy < Cache 7 | class Update < Proxy 8 | self.summary = '更新缓存代理' 9 | 10 | self.description = <<-DESC 11 | 更新缓存代理 12 | DESC 13 | 14 | self.arguments = [ 15 | CLAide::Argument.new('NAME', true), 16 | CLAide::Argument.new('URL', true), 17 | CLAide::Argument.new('USER', true), 18 | CLAide::Argument.new('PASSWORD', true) 19 | ] 20 | 21 | def initialize(argv) 22 | init 23 | @name, @url, @user, @password = argv.shift_argument, argv.shift_argument, argv.shift_argument, argv.shift_argument 24 | @silent = argv.flag?('silent', false) 25 | super 26 | end 27 | 28 | def validate! 29 | super 30 | help! 'This command requires both a repo name.' unless @name 31 | help! 'This command requires both a repo url.' unless @url 32 | help! 'This command requires both a repo user.' unless @user 33 | help! 'This command requires both a repo password.' unless @password 34 | end 35 | 36 | def run 37 | raise Pod::Informative.exception "`#{@name}` 不存在" unless CPSH.check_source_conf_exists(@name) 38 | 39 | UI.section("Update cache proxy repo `#{@name}`".green) do 40 | CPSH.init_cache_proxy_source(@name, @url, @user, @password) 41 | end 42 | end 43 | end 44 | end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/gem_version.rb: -------------------------------------------------------------------------------- 1 | module CocoapodsCacheProxy 2 | VERSION = "0.0.2".freeze 3 | end 4 | 5 | module Pod 6 | def self.match_version?(*version) 7 | Gem::Dependency.new("", *version).match?('', Pod::VERSION) 8 | end 9 | end -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/helper/cache_proxy_source_helper.rb: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | require 'find' 3 | require 'json' 4 | require 'cocoapods' 5 | require 'yaml' 6 | require 'uri' 7 | require 'pathname' 8 | require 'cocoapods-cache-proxy/native/cache_proxy_source' 9 | require 'cocoapods-cache-proxy/native/cache_proxy_auth' 10 | 11 | module Pod 12 | class CacheProxySource 13 | class CacheProxySourceHelper 14 | 15 | # @return [String] 16 | def self.get_cache_proxy_root_dir 17 | "#{Pod::Config.instance.home_dir}/cache-proxy" 18 | end 19 | 20 | # @param [String] source_name 21 | # @return [String] 22 | def self.get_source_root_dir(source_name) 23 | "#{Pod::Config.instance.home_dir}/cache-proxy/#{source_name}" 24 | end 25 | 26 | 27 | # @return [String] 28 | def self.get_auth_root_dir 29 | "#{Pod::Config.instance.home_dir}/cache-proxy-auth" 30 | end 31 | 32 | 33 | # @return [String] 34 | def self.get_auth_conf_file_name 35 | ".auth_conf.yml" 36 | end 37 | 38 | 39 | # @param [String] host 40 | # @return [String] 41 | def self.get_auth_conf_path(host) 42 | uri = URI.parse(host) 43 | "#{get_auth_root_dir}/#{uri.host}/#{get_auth_conf_file_name}" 44 | end 45 | 46 | # @param [String] host 47 | # @return [TrueClass, FalseClass] 48 | def self.check_auth_conf_exists(host) 49 | File.exist?(get_auth_conf_path(host)) 50 | end 51 | 52 | # @param [String] host 53 | # @return [Hash] 54 | def self.load_auth_conf_host(host) 55 | path = get_auth_conf_path(host) 56 | if File.exist?(path) 57 | YAML.load_file(path) 58 | else 59 | nil 60 | end 61 | end 62 | 63 | # @param [String] path 64 | # @return [Hash] 65 | def self.load_auth_conf_path(path) 66 | if File.exist?(path) 67 | YAML.load_file(path) 68 | else 69 | nil 70 | end 71 | end 72 | 73 | # @@return [String] 74 | def self.get_source_conf_file_name 75 | ".cache_proxy_conf.yml" 76 | end 77 | 78 | # @param [String] source_name 79 | # @return [String] 80 | def self.get_source_conf_path(source_name) 81 | "#{get_source_root_dir(source_name)}/#{get_source_conf_file_name}" 82 | end 83 | 84 | # @param [String] source_name 85 | # @return [Void] 86 | def self.check_source_conf_exists(source_name) 87 | File.exist?(get_source_conf_path(source_name)) 88 | end 89 | 90 | # @param [String] source_name 91 | # @return [Hash] 92 | def self.load_source_conf(source_name) 93 | path = get_source_conf_path(source_name) 94 | if File.exist?(path) 95 | YAML.load_file(path) 96 | else 97 | nil 98 | end 99 | end 100 | 101 | # @param [String] host 102 | # @param [String] token 103 | # @return [Void] 104 | def self.save_cache_proxy_auth_conf(host, token) 105 | path = get_auth_conf_path(host) 106 | auth = { 107 | 'host' => host, 108 | 'token' => token, 109 | } 110 | 111 | conf = File.new(path, "wb") 112 | conf << auth.to_yaml 113 | conf.close 114 | end 115 | 116 | # @param [String] host 117 | # @param [String] token 118 | # @return [Void] 119 | def self.init_cache_proxy_auth(host, token) 120 | begin 121 | 122 | show_output = Pod::Config.instance.verbose? 123 | pn = Pathname(get_auth_conf_path(host)) 124 | 125 | FileUtils.mkdir_p(pn.parent) unless Dir.exist?(pn.parent) 126 | 127 | Pod::UI.message "Generating auth conf .....".yellow if show_output 128 | save_cache_proxy_auth_conf(host, token) 129 | Pod::UI.message "Successfully added auth #{host} ".green if show_output 130 | 131 | rescue Exception => e 132 | Pod::UI.message "发生异常,清理文件 .....".yellow if show_output 133 | pn = Pathname(get_auth_conf_path(host)) 134 | FileUtils.rm_rf(pn.parent) if Dir.exist?(pn.parent) 135 | Pod::UI.message e.message.yellow if show_output 136 | Pod::UI.message e.backtrace.inspect.yellow if show_output 137 | raise e 138 | end 139 | end 140 | 141 | # @param [String] host 142 | # @return [Void] 143 | def self.remove_cache_proxy_auth(host) 144 | show_output = Pod::Config.instance.verbose? 145 | path = Pathname(get_auth_conf_path(host)) 146 | FileUtils.rm_rf(path.parent) if Dir.exist?(path.parent) 147 | 148 | Pod::UI.message "Successfully remove auth #{host}".green if show_output 149 | end 150 | 151 | # @param [String] host 152 | # @return [Pod::CacheProxyAuth] 153 | def self.get_cache_proxy_auth_conf_host(host) 154 | return nil unless (cnf = load_auth_conf_host(host)) 155 | Pod::CacheProxyAuth.new(cnf['host'], cnf['token']) 156 | end 157 | 158 | # @param [String] path 159 | # @return [Pod::CacheProxyAuth] 160 | def self.get_cache_proxy_auth_conf_path(path) 161 | return nil unless (cnf = load_auth_conf_path(path)) 162 | Pod::CacheProxyAuth.new(cnf['host'], cnf['token']) 163 | end 164 | 165 | # @return [Array] 166 | def self.get_all_auths 167 | return [] unless Dir.exist?(get_auth_root_dir) 168 | list = [] 169 | Find.find(get_auth_root_dir) do |path| 170 | next unless File.file?(path) && path.end_with?(get_auth_conf_file_name) 171 | next unless (conf = get_cache_proxy_auth_conf_path(path)) 172 | next if conf.host.blank? || conf.token.blank? 173 | list << conf 174 | end 175 | list 176 | end 177 | 178 | # @param [String] source_name 179 | # @param [String] url 180 | # @param [String] user 181 | # @param [String] password 182 | # @return [Void] 183 | def self.save_cache_proxy_source_conf(source_name, url, user, password) 184 | path = get_source_conf_path(source_name) 185 | info = { 186 | 'name' => source_name, 187 | 'url' => url, 188 | } 189 | 190 | info['user'] = user unless user.blank? 191 | info['password'] = password unless password.blank? 192 | 193 | conf = File.new(path, "wb") 194 | conf << info.to_yaml 195 | conf.close 196 | 197 | end 198 | 199 | 200 | # @param [String] cache_source_name 201 | # @param [String] cache_source_url 202 | # @param [String] user 203 | # @param [String] password 204 | # @return [Void] 205 | def self.init_cache_proxy_source(cache_source_name, cache_source_url, user, password) 206 | begin 207 | show_output = Pod::Config.instance.verbose? 208 | 209 | cache_source_root_path = "#{get_source_root_dir(cache_source_name)}" 210 | 211 | FileUtils.rm_rf(cache_source_root_path) if Dir.exist?(cache_source_root_path) 212 | 213 | FileUtils.mkdir_p(cache_source_root_path) 214 | 215 | Pod::UI.message "Generating source conf .....".yellow if show_output 216 | save_cache_proxy_source_conf(cache_source_name, cache_source_url, user, password) 217 | Pod::UI.message "Successfully added repo #{cache_source_name}".green if show_output 218 | 219 | rescue Exception => e 220 | Pod::UI.message "发生异常,清理文件 .....".yellow if show_output 221 | FileUtils.rm_rf(cache_source_root_path) if Dir.exist?(cache_source_root_path) 222 | Pod::UI.message e.message.yellow if show_output 223 | Pod::UI.message e.backtrace.inspect.yellow if show_output 224 | raise e 225 | end 226 | end 227 | 228 | # @param [String] cache_source_name 229 | # @return [Void] 230 | def self.remove_cache_proxy_source(cache_source_name) 231 | show_output = Pod::Config.instance.verbose? 232 | 233 | cache_source_root_path = "#{get_source_root_dir(cache_source_name)}" 234 | FileUtils.rm_rf(cache_source_root_path) if Dir.exist?(cache_source_root_path) 235 | 236 | Pod::UI.message "Successfully remove repo #{cache_source_name}".green if show_output 237 | end 238 | 239 | # @param [String] cache_source_name 240 | # @return [Pod::CacheProxySource] 241 | def self.get_cache_proxy_source_conf(cache_source_name) 242 | return nil unless (cnf = load_source_conf(cache_source_name)) 243 | Pod::CacheProxySource.new(cnf['name'], cnf['url'], cnf['user'], cnf['password']) 244 | end 245 | 246 | # @return [Array] 247 | def self.get_all_sources 248 | return [] unless Dir.exist?(get_cache_proxy_root_dir) 249 | list = [] 250 | Find.find(get_cache_proxy_root_dir) do |path| 251 | next unless File.file?(path) && path.end_with?(get_source_conf_file_name) 252 | pn = Pathname.new(path) 253 | source_name = pn.dirname.basename 254 | next unless (conf = get_cache_proxy_source_conf(source_name)) 255 | list << conf 256 | end 257 | list 258 | end 259 | end 260 | end 261 | end 262 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/helper/helper.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/helper/cache_proxy_source_helper' 2 | 3 | CPSH = Pod::CacheProxySource::CacheProxySourceHelper -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/native/cache_proxy_auth.rb: -------------------------------------------------------------------------------- 1 | module Pod 2 | class CacheProxyAuth 3 | 4 | # @param [String] host 5 | # @param [String] token 6 | def initialize(host, token) 7 | @host = host 8 | @token = token 9 | end 10 | 11 | # @return [String] 12 | def host 13 | @host 14 | end 15 | 16 | def token 17 | @token 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/native/cache_proxy_source.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/helper/helper' 2 | require 'cocoapods-cache-proxy/native/cache_proxy_auth' 3 | require 'uri' 4 | 5 | module Pod 6 | class CacheProxySource 7 | 8 | 9 | # @param [String] name 10 | # @param [String] baseURL 11 | # @param [String] user 12 | # @param [String] password 13 | def initialize(name, baseURL, user, password) 14 | @name = name 15 | @baseURL = baseURL 16 | @user = user 17 | @password = password 18 | end 19 | 20 | 21 | # @return [String] 22 | def name 23 | @name 24 | end 25 | 26 | def baseURL 27 | @baseURL 28 | end 29 | 30 | def user 31 | @user 32 | end 33 | 34 | def password 35 | @password 36 | end 37 | 38 | # @param [String] pod pod name 39 | # @param [String] git repo address 40 | # @param [String] tag repo tag 41 | # @param [String] submodules need update submodules 42 | # @return [String] full download url 43 | def build_proxy_source(pod, git, tag, submodules = false) 44 | auth_cnf = CPSH.get_cache_proxy_auth_conf_host(git) 45 | if auth_cnf.nil? 46 | uri = URI.parse("#{@baseURL}/#{pod}?git=#{git}&tag=#{tag}&submodules=#{submodules}&cache_proxy=1") 47 | uri.user = @user 48 | uri.password = @password 49 | uri.to_s 50 | else 51 | uri = URI.parse(git) 52 | uri.user = "oauth2" 53 | uri.password = auth_cnf.token 54 | url = uri.to_s 55 | uri = URI.parse("#{@baseURL}/#{pod}?git=#{url}&tag=#{tag}&submodules=#{submodules}&cache_proxy=1") 56 | uri.user = @user 57 | uri.password = @password 58 | uri.to_s 59 | end 60 | end 61 | end 62 | end -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/native/config.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/native/cache_proxy_source' 2 | require 'cocoapods-cache-proxy/helper/helper' 3 | 4 | module Pod 5 | class Config 6 | attr_reader :cache_proxy_source 7 | 8 | # @param [String] name 9 | # @return [Pod::CacheProxySource] 10 | def set_cache_proxy_source(name) 11 | return if name.blank? 12 | return unless (cnf = CPSH.get_cache_proxy_source_conf(name)) 13 | @cache_proxy_source = cnf 14 | end 15 | 16 | # @return [Pod::CacheProxySource] 17 | def cache_proxy_source 18 | @cache_proxy_source 19 | end 20 | 21 | # @return [TrueClass, FalseClass] 22 | def cache_proxy_source_available 23 | !@cache_proxy_source.nil? 24 | end 25 | 26 | # def remove_cache_proxy_source(name) 27 | # return if name.blank? || @cache_proxy_source.nil? || @cache_proxy_source.empty? 28 | # @cache_proxy_source.delete_if { |cnf| cnf.name == name } 29 | # end 30 | 31 | # def get_all_cache_proxy_sources() 32 | # return [] if @cache_proxy_source.nil? 33 | # @cache_proxy_source 34 | # end 35 | end 36 | end -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/native/downloader.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-downloader' 2 | require 'cocoapods' 3 | 4 | # module Pod 5 | # module Downloader 6 | # class Cache 7 | # alias_method :orig_copy_and_clean, :copy_and_clean 8 | # def copy_and_clean(source, destination, spec) 9 | # # specs_by_platform = group_subspecs_by_platform(spec) 10 | # # destination.parent.mkpath 11 | # # FileUtils.rm_rf(destination) 12 | # # FileUtils.cp_r(source, destination) 13 | # # Pod::Installer::PodSourcePreparer.new(spec, destination).prepare! 14 | # # Sandbox::PodDirCleaner.new(destination, specs_by_platform).clean! 15 | # Pod::UI.message "copy_and_clean: \n" 16 | # Pod::UI.message "spec: #{spec.class}" 17 | # Pod::UI.message "source: #{source}" 18 | # Pod::UI.message "destination: #{destination}" 19 | # Pod::UI.message "destination parent: #{destination.parent}" 20 | # Pod::UI.message "destination parent basename: #{destination.basename}" 21 | # p = "/Users/king/Desktop/#{source.basename}" 22 | # FileUtils.rm_rf(p) 23 | # FileUtils.cp_r(source, p) 24 | # # exit 0 25 | # orig_copy_and_clean(source, destination, spec) 26 | # # exit 0 27 | # end 28 | # end 29 | # end 30 | # end 31 | 32 | module Pod 33 | module Downloader 34 | class Http 35 | 36 | alias_method :orig_download_file, :download_file 37 | 38 | def download_file(full_filename) 39 | download_uri = URI(url) 40 | 41 | if !download_uri.query.blank? && download_uri.query.include?("git=") && download_uri.query.include?("tag=") && download_uri.query.include?("cache_proxy=1") 42 | curl_options = ["-f", "-L", "-o", full_filename, url, "--create-dirs"] 43 | curl! curl_options 44 | else 45 | orig_download_file(full_filename) 46 | end 47 | end 48 | end 49 | end 50 | end -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/native/installer.rb: -------------------------------------------------------------------------------- 1 | 2 | # module Pod 3 | # class Installer 4 | 5 | # # alias_method :old_specs_for_pod, :specs_for_pod 6 | # # def specs_for_pod(pod_name) 7 | # # specs_by_platform = old_specs_for_pod(pod_name) 8 | # # specs = specs_by_platform.values.flatten 9 | # # root_spec = specs.first.root 10 | # # UI.message "specs_by_platform values name: #{specs}" 11 | # # UI.message "specs_by_platform root_spec name: #{root_spec.name}" 12 | # # UI.message "specs_by_platform root_spec version: #{root_spec.version}" 13 | # # UI.message "specs_by_platform origin source: #{root_spec.source}" 14 | # # root_spec.source = { :http => 'http://127.0.0.1:9898/static/AFNetworking.zip'} 15 | # # UI.message "specs_by_platform proxy source: #{root_spec.source}" 16 | # # # exit 0 17 | # # specs_by_platform 18 | # # end 19 | # end 20 | # end -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/native/native.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/native/downloader' 2 | require 'cocoapods-cache-proxy/native/resolver' 3 | require 'cocoapods-cache-proxy/native/podfile_dsl' 4 | require 'cocoapods-cache-proxy/native/cache_proxy_source' 5 | require 'cocoapods-cache-proxy/native/config' 6 | # require 'cocoapods-cache-proxy/native/installer' 7 | -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/native/podfile_dsl.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-core' 2 | 3 | module Pod 4 | class Podfile 5 | module DSL 6 | 7 | def ignore_cache_proxy_pods!(pods = []) 8 | current_target_definition.set_ignore_cache_proxy_pods(pods) if !pods.blank? && !current_target_definition.nil? 9 | end 10 | end 11 | end 12 | end 13 | 14 | 15 | module Pod 16 | class Podfile 17 | 18 | class IgnorePodProxy 19 | def self.keyword 20 | :ignore_cache_proxy 21 | end 22 | end 23 | 24 | class UsedPodProxySource 25 | def self.keyword 26 | :cache_proxy_source 27 | end 28 | end 29 | 30 | class TargetDefinition 31 | attr_reader :ignore_cache_proxy 32 | attr_reader :cache_proxy_source 33 | 34 | #alias_method :orig_store_pod, :store_pod 35 | #def store_pod(name, *requirements) 36 | # Pod::UI.message "store_pod requirements: #{requirements}" if Pod::Config.instance.verbose? 37 | # #parse_ignore_cache_proxy(name, requirements) 38 | # options = requirements.last 39 | # if options.is_a?(Hash) and options.has_key?(:ignore_cache_proxy) 40 | # Pod::UI.message "ignore_cache_proxy name: #{name}" 41 | # options.delete(:ignore_cache_proxy) 42 | # requirements.pop if options.empty? 43 | # end 44 | # Pod::UI.message "store_pod 2 requirements: #{requirements}" if Pod::Config.instance.verbose? 45 | # orig_store_pod(name, *requirements) 46 | #end 47 | 48 | # ---- patch method ---- 49 | # We want modify `store_pod` method, but it's hard to insert a line in the 50 | # implementation. So we patch a method called in `store_pod`. 51 | alias_method :orig_parse_inhibit_warnings, :parse_inhibit_warnings 52 | def parse_inhibit_warnings(name, requirements) 53 | options = requirements.last 54 | 55 | if options.is_a?(Hash) 56 | if options.has_key?(Pod::Podfile::IgnorePodProxy.keyword) 57 | ignore = options[Pod::Podfile::IgnorePodProxy.keyword] 58 | options.delete(Pod::Podfile::IgnorePodProxy.keyword) 59 | set_ignore_cache_proxy_pods([name]) if ignore 60 | end 61 | 62 | if options.has_key?(Pod::Podfile::UsedPodProxySource.keyword) 63 | source_name = options[Pod::Podfile::UsedPodProxySource.keyword] 64 | options.delete(Pod::Podfile::UsedPodProxySource.keyword) 65 | unless source_name.blank? 66 | raise Pod::Informative.exception "cache proxy source: `#{source_name}` source does not exist." unless (source = CPSH.get_cache_proxy_source_conf(source_name)) 67 | @cache_proxy_source = Hash.new if @cache_proxy_source.nil? 68 | @cache_proxy_source[name] = source 69 | end 70 | end 71 | requirements.pop if options.empty? 72 | end 73 | orig_parse_inhibit_warnings(name, requirements) 74 | end 75 | 76 | # 参考 https://github.com/leavez/cocoapods-binary/blob/9f40c5df4149598b03b44c01d33b04e78ff38772/lib/cocoapods-binary/helper/podfile_options.rb#L52-L60 77 | # ---- patch method ---- 78 | # We want modify `store_pod` method, but it's hard to insert a line in the 79 | # implementation. So we patch a method called in `store_pod`. 80 | #old_method = instance_method(:parse_inhibit_warnings) 81 | # 82 | #define_method(:parse_inhibit_warnings) do |name, requirements| 83 | # Pod::UI.message "parse_inhibit_warnings requirements: #{requirements}" if Pod::Config.instance.verbose? 84 | # options = requirements.last 85 | # if options.is_a?(Hash) and options.has_key?(:ignore_cache_proxy) 86 | # Pod::UI.message "ignore_cache_proxy name: #{name}" 87 | # options.delete(:ignore_cache_proxy) 88 | # requirements.pop if options.empty? 89 | # set_ignore_cache_proxy_pods([name]) 90 | # end 91 | # Pod::UI.message "parse_inhibit_warnings requirements: #{requirements}" if Pod::Config.instance.verbose? 92 | # old_method.bind(self).(name, requirements) 93 | #end 94 | 95 | #def parse_ignore_cache_proxy(name, requirements) 96 | # requirements.each do |options| 97 | # next unless options.is_a?(Hash) 98 | # Pod::UI.message "parse_ignore_cache_proxy: #{options}" if Pod::Config.instance.verbose? 99 | # set_ignore_cache_proxy_pods([name]) if options.has_key?(:git) 100 | # end 101 | #end 102 | 103 | # @param [Array] pods 104 | def set_ignore_cache_proxy_pods(pods) 105 | return if pods.blank? 106 | @ignore_cache_proxy = [] if @ignore_cache_proxy.nil? 107 | pods.uniq.each do |pod| 108 | @ignore_cache_proxy << pod unless @ignore_cache_proxy.include?(pod) 109 | end 110 | end 111 | 112 | # @return [Array] 113 | def get_ignore_cache_proxy_pods 114 | @ignore_cache_proxy.nil? ? [] : @ignore_cache_proxy.uniq 115 | end 116 | 117 | # @param [String] pod 118 | # @return [TrueClass, FalseClass] 119 | def check_ignore_cache_proxy_pod(pod) 120 | return false if pod.blank? 121 | ignores = [] 122 | ignores.concat(get_ignore_cache_proxy_pods) 123 | ignores.concat(root.get_ignore_cache_proxy_pods) unless root.nil? 124 | ignores.concat(parent.get_ignore_cache_proxy_pods) unless parent.nil? 125 | ignores.uniq.include?(pod) 126 | end 127 | 128 | # @param [String] pod 129 | # @return [CacheProxySource] 130 | def proxy_source_for_pod(pod) 131 | return nil if @cache_proxy_source.blank? 132 | @cache_proxy_source[pod] 133 | end 134 | end 135 | end 136 | end -------------------------------------------------------------------------------- /lib/cocoapods-cache-proxy/native/resolver.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods' 2 | require 'cocoapods-cache-proxy/native/config' 3 | require 'cocoapods-cache-proxy/native/podfile_dsl' 4 | require 'cocoapods-cache-proxy/gem_version' 5 | 6 | module Pod 7 | class Resolver 8 | 9 | alias_method :orig_resolver_specs_by_target, :resolver_specs_by_target 10 | def resolver_specs_by_target 11 | specs_by_target = orig_resolver_specs_by_target 12 | 13 | return specs_by_target unless Pod::Config.instance.cache_proxy_source_available 14 | root_proxy_source = Pod::Config.instance.cache_proxy_source 15 | 16 | specs_by_target.each do |target, specs| 17 | specs.each do |spec| 18 | root_spec = spec.spec.root 19 | source = root_spec.source 20 | next unless !source.blank? && source.has_key?(:git) && source.has_key?(:tag) 21 | next if target.check_ignore_cache_proxy_pod(root_spec.name) 22 | 23 | git = source[:git] 24 | tag = source[:tag] 25 | submodules = source.has_key?(:submodules) ? source[:submodules] : false 26 | 27 | proxy_source = target.proxy_source_for_pod(root_spec.name) 28 | new_url = (proxy_source.nil? ? root_proxy_source : proxy_source).build_proxy_source(root_spec.name, git, tag, submodules) 29 | source = { 30 | :http => new_url, 31 | :type => "tgz", 32 | } 33 | root_spec.source = source 34 | end 35 | end 36 | specs_by_target 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/cocoapods_plugin.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-cache-proxy/command' 2 | require 'hook' -------------------------------------------------------------------------------- /lib/hook.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods' 2 | require 'cocoapods-downloader' 3 | require 'cocoapods-cache-proxy/native/native' 4 | require 'cocoapods-cache-proxy/helper/helper' 5 | require 'yaml' 6 | require 'uri' 7 | 8 | 9 | Pod::HooksManager.register('cocoapods-cache-proxy', :source_provider) do |context, options| 10 | show_output = Pod::Config.instance.verbose? 11 | Pod::UI.message 'cocoapods-cache-proxy received source_provider hook' if show_output 12 | 13 | return unless (proxy_name = options['proxy']) 14 | raise Pod::Informative.exception "cache proxy source: `#{proxy_name}` source does not exist." unless CPSH.check_source_conf_exists(proxy_name) 15 | Pod::UI.message "proxy_name: #{proxy_name}" if show_output 16 | Pod::Config.instance.set_cache_proxy_source(proxy_name) 17 | end 18 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3CD8D96723C47DAE00993762 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CD8D96623C47DAE00993762 /* AppDelegate.m */; }; 11 | 3CD8D96A23C47DAE00993762 /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CD8D96923C47DAE00993762 /* SceneDelegate.m */; }; 12 | 3CD8D96D23C47DAE00993762 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CD8D96C23C47DAE00993762 /* ViewController.m */; }; 13 | 3CD8D97023C47DAE00993762 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3CD8D96E23C47DAE00993762 /* Main.storyboard */; }; 14 | 3CD8D97223C47DB100993762 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3CD8D97123C47DB100993762 /* Assets.xcassets */; }; 15 | 3CD8D97523C47DB100993762 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3CD8D97323C47DB100993762 /* LaunchScreen.storyboard */; }; 16 | 3CD8D97823C47DB100993762 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CD8D97723C47DB100993762 /* main.m */; }; 17 | B946D3CC9A5E9D071DD3E4A9 /* Pods_CocopodsCacheProxy_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37CFCE5D097F50BDF3382275 /* Pods_CocopodsCacheProxy_Demo.framework */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 37CFCE5D097F50BDF3382275 /* Pods_CocopodsCacheProxy_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CocopodsCacheProxy_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 3C625C5C23CDA34100F60DCF /* Gemfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Gemfile; sourceTree = ""; }; 23 | 3CD8D96223C47DAE00993762 /* CocopodsCacheProxy-Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "CocopodsCacheProxy-Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 3CD8D96523C47DAE00993762 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 25 | 3CD8D96623C47DAE00993762 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 26 | 3CD8D96823C47DAE00993762 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; }; 27 | 3CD8D96923C47DAE00993762 /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = ""; }; 28 | 3CD8D96B23C47DAE00993762 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 29 | 3CD8D96C23C47DAE00993762 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 30 | 3CD8D96F23C47DAE00993762 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 31 | 3CD8D97123C47DB100993762 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 32 | 3CD8D97423C47DB100993762 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 33 | 3CD8D97623C47DB100993762 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 34 | 3CD8D97723C47DB100993762 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 35 | 5ACC61A870B0C068C52BC577 /* Pods-CocopodsCacheProxy-Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CocopodsCacheProxy-Demo.release.xcconfig"; path = "Target Support Files/Pods-CocopodsCacheProxy-Demo/Pods-CocopodsCacheProxy-Demo.release.xcconfig"; sourceTree = ""; }; 36 | A157BAA979FB8BA0E1AC1051 /* Pods-CocopodsCacheProxy-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CocopodsCacheProxy-Demo.debug.xcconfig"; path = "Target Support Files/Pods-CocopodsCacheProxy-Demo/Pods-CocopodsCacheProxy-Demo.debug.xcconfig"; sourceTree = ""; }; 37 | /* End PBXFileReference section */ 38 | 39 | /* Begin PBXFrameworksBuildPhase section */ 40 | 3CD8D95F23C47DAE00993762 /* Frameworks */ = { 41 | isa = PBXFrameworksBuildPhase; 42 | buildActionMask = 2147483647; 43 | files = ( 44 | B946D3CC9A5E9D071DD3E4A9 /* Pods_CocopodsCacheProxy_Demo.framework in Frameworks */, 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 3CD8D95923C47DAE00993762 = { 52 | isa = PBXGroup; 53 | children = ( 54 | 3C625C5C23CDA34100F60DCF /* Gemfile */, 55 | 3CD8D96423C47DAE00993762 /* CocopodsCacheProxy-Demo */, 56 | 3CD8D96323C47DAE00993762 /* Products */, 57 | 65EB3440D6F2FFECF963AD9A /* Pods */, 58 | C0587ABD80EF314077CED281 /* Frameworks */, 59 | ); 60 | sourceTree = ""; 61 | }; 62 | 3CD8D96323C47DAE00993762 /* Products */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | 3CD8D96223C47DAE00993762 /* CocopodsCacheProxy-Demo.app */, 66 | ); 67 | name = Products; 68 | sourceTree = ""; 69 | }; 70 | 3CD8D96423C47DAE00993762 /* CocopodsCacheProxy-Demo */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 3CD8D96523C47DAE00993762 /* AppDelegate.h */, 74 | 3CD8D96623C47DAE00993762 /* AppDelegate.m */, 75 | 3CD8D96823C47DAE00993762 /* SceneDelegate.h */, 76 | 3CD8D96923C47DAE00993762 /* SceneDelegate.m */, 77 | 3CD8D96B23C47DAE00993762 /* ViewController.h */, 78 | 3CD8D96C23C47DAE00993762 /* ViewController.m */, 79 | 3CD8D96E23C47DAE00993762 /* Main.storyboard */, 80 | 3CD8D97123C47DB100993762 /* Assets.xcassets */, 81 | 3CD8D97323C47DB100993762 /* LaunchScreen.storyboard */, 82 | 3CD8D97623C47DB100993762 /* Info.plist */, 83 | 3CD8D97723C47DB100993762 /* main.m */, 84 | ); 85 | path = "CocopodsCacheProxy-Demo"; 86 | sourceTree = ""; 87 | }; 88 | 65EB3440D6F2FFECF963AD9A /* Pods */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | A157BAA979FB8BA0E1AC1051 /* Pods-CocopodsCacheProxy-Demo.debug.xcconfig */, 92 | 5ACC61A870B0C068C52BC577 /* Pods-CocopodsCacheProxy-Demo.release.xcconfig */, 93 | ); 94 | path = Pods; 95 | sourceTree = ""; 96 | }; 97 | C0587ABD80EF314077CED281 /* Frameworks */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 37CFCE5D097F50BDF3382275 /* Pods_CocopodsCacheProxy_Demo.framework */, 101 | ); 102 | name = Frameworks; 103 | sourceTree = ""; 104 | }; 105 | /* End PBXGroup section */ 106 | 107 | /* Begin PBXNativeTarget section */ 108 | 3CD8D96123C47DAE00993762 /* CocopodsCacheProxy-Demo */ = { 109 | isa = PBXNativeTarget; 110 | buildConfigurationList = 3CD8D97B23C47DB100993762 /* Build configuration list for PBXNativeTarget "CocopodsCacheProxy-Demo" */; 111 | buildPhases = ( 112 | 47BDBBF60CBB8B08309932D2 /* [CP] Check Pods Manifest.lock */, 113 | 3CD8D95E23C47DAE00993762 /* Sources */, 114 | 3CD8D95F23C47DAE00993762 /* Frameworks */, 115 | 3CD8D96023C47DAE00993762 /* Resources */, 116 | 01E5A13D55EA2DC4B5BB713F /* [CP] Embed Pods Frameworks */, 117 | ); 118 | buildRules = ( 119 | ); 120 | dependencies = ( 121 | ); 122 | name = "CocopodsCacheProxy-Demo"; 123 | productName = "CocopodsCacheProxy-Demo"; 124 | productReference = 3CD8D96223C47DAE00993762 /* CocopodsCacheProxy-Demo.app */; 125 | productType = "com.apple.product-type.application"; 126 | }; 127 | /* End PBXNativeTarget section */ 128 | 129 | /* Begin PBXProject section */ 130 | 3CD8D95A23C47DAE00993762 /* Project object */ = { 131 | isa = PBXProject; 132 | attributes = { 133 | LastUpgradeCheck = 1120; 134 | ORGANIZATIONNAME = "K&K"; 135 | TargetAttributes = { 136 | 3CD8D96123C47DAE00993762 = { 137 | CreatedOnToolsVersion = 11.2.1; 138 | }; 139 | }; 140 | }; 141 | buildConfigurationList = 3CD8D95D23C47DAE00993762 /* Build configuration list for PBXProject "CocopodsCacheProxy-Demo" */; 142 | compatibilityVersion = "Xcode 9.3"; 143 | developmentRegion = en; 144 | hasScannedForEncodings = 0; 145 | knownRegions = ( 146 | en, 147 | Base, 148 | ); 149 | mainGroup = 3CD8D95923C47DAE00993762; 150 | productRefGroup = 3CD8D96323C47DAE00993762 /* Products */; 151 | projectDirPath = ""; 152 | projectRoot = ""; 153 | targets = ( 154 | 3CD8D96123C47DAE00993762 /* CocopodsCacheProxy-Demo */, 155 | ); 156 | }; 157 | /* End PBXProject section */ 158 | 159 | /* Begin PBXResourcesBuildPhase section */ 160 | 3CD8D96023C47DAE00993762 /* Resources */ = { 161 | isa = PBXResourcesBuildPhase; 162 | buildActionMask = 2147483647; 163 | files = ( 164 | 3CD8D97523C47DB100993762 /* LaunchScreen.storyboard in Resources */, 165 | 3CD8D97223C47DB100993762 /* Assets.xcassets in Resources */, 166 | 3CD8D97023C47DAE00993762 /* Main.storyboard in Resources */, 167 | ); 168 | runOnlyForDeploymentPostprocessing = 0; 169 | }; 170 | /* End PBXResourcesBuildPhase section */ 171 | 172 | /* Begin PBXShellScriptBuildPhase section */ 173 | 01E5A13D55EA2DC4B5BB713F /* [CP] Embed Pods Frameworks */ = { 174 | isa = PBXShellScriptBuildPhase; 175 | buildActionMask = 2147483647; 176 | files = ( 177 | ); 178 | inputFileListPaths = ( 179 | "${PODS_ROOT}/Target Support Files/Pods-CocopodsCacheProxy-Demo/Pods-CocopodsCacheProxy-Demo-frameworks-${CONFIGURATION}-input-files.xcfilelist", 180 | ); 181 | name = "[CP] Embed Pods Frameworks"; 182 | outputFileListPaths = ( 183 | "${PODS_ROOT}/Target Support Files/Pods-CocopodsCacheProxy-Demo/Pods-CocopodsCacheProxy-Demo-frameworks-${CONFIGURATION}-output-files.xcfilelist", 184 | ); 185 | runOnlyForDeploymentPostprocessing = 0; 186 | shellPath = /bin/sh; 187 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CocopodsCacheProxy-Demo/Pods-CocopodsCacheProxy-Demo-frameworks.sh\"\n"; 188 | showEnvVarsInLog = 0; 189 | }; 190 | 47BDBBF60CBB8B08309932D2 /* [CP] Check Pods Manifest.lock */ = { 191 | isa = PBXShellScriptBuildPhase; 192 | buildActionMask = 2147483647; 193 | files = ( 194 | ); 195 | inputFileListPaths = ( 196 | ); 197 | inputPaths = ( 198 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 199 | "${PODS_ROOT}/Manifest.lock", 200 | ); 201 | name = "[CP] Check Pods Manifest.lock"; 202 | outputFileListPaths = ( 203 | ); 204 | outputPaths = ( 205 | "$(DERIVED_FILE_DIR)/Pods-CocopodsCacheProxy-Demo-checkManifestLockResult.txt", 206 | ); 207 | runOnlyForDeploymentPostprocessing = 0; 208 | shellPath = /bin/sh; 209 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 210 | showEnvVarsInLog = 0; 211 | }; 212 | /* End PBXShellScriptBuildPhase section */ 213 | 214 | /* Begin PBXSourcesBuildPhase section */ 215 | 3CD8D95E23C47DAE00993762 /* Sources */ = { 216 | isa = PBXSourcesBuildPhase; 217 | buildActionMask = 2147483647; 218 | files = ( 219 | 3CD8D96D23C47DAE00993762 /* ViewController.m in Sources */, 220 | 3CD8D96723C47DAE00993762 /* AppDelegate.m in Sources */, 221 | 3CD8D97823C47DB100993762 /* main.m in Sources */, 222 | 3CD8D96A23C47DAE00993762 /* SceneDelegate.m in Sources */, 223 | ); 224 | runOnlyForDeploymentPostprocessing = 0; 225 | }; 226 | /* End PBXSourcesBuildPhase section */ 227 | 228 | /* Begin PBXVariantGroup section */ 229 | 3CD8D96E23C47DAE00993762 /* Main.storyboard */ = { 230 | isa = PBXVariantGroup; 231 | children = ( 232 | 3CD8D96F23C47DAE00993762 /* Base */, 233 | ); 234 | name = Main.storyboard; 235 | sourceTree = ""; 236 | }; 237 | 3CD8D97323C47DB100993762 /* LaunchScreen.storyboard */ = { 238 | isa = PBXVariantGroup; 239 | children = ( 240 | 3CD8D97423C47DB100993762 /* Base */, 241 | ); 242 | name = LaunchScreen.storyboard; 243 | sourceTree = ""; 244 | }; 245 | /* End PBXVariantGroup section */ 246 | 247 | /* Begin XCBuildConfiguration section */ 248 | 3CD8D97923C47DB100993762 /* Debug */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | ALWAYS_SEARCH_USER_PATHS = NO; 252 | CLANG_ANALYZER_NONNULL = YES; 253 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 254 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 255 | CLANG_CXX_LIBRARY = "libc++"; 256 | CLANG_ENABLE_MODULES = YES; 257 | CLANG_ENABLE_OBJC_ARC = YES; 258 | CLANG_ENABLE_OBJC_WEAK = YES; 259 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 260 | CLANG_WARN_BOOL_CONVERSION = YES; 261 | CLANG_WARN_COMMA = YES; 262 | CLANG_WARN_CONSTANT_CONVERSION = YES; 263 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 264 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 265 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 266 | CLANG_WARN_EMPTY_BODY = YES; 267 | CLANG_WARN_ENUM_CONVERSION = YES; 268 | CLANG_WARN_INFINITE_RECURSION = YES; 269 | CLANG_WARN_INT_CONVERSION = YES; 270 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 271 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 272 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 273 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 274 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 275 | CLANG_WARN_STRICT_PROTOTYPES = YES; 276 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 277 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 278 | CLANG_WARN_UNREACHABLE_CODE = YES; 279 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 280 | COPY_PHASE_STRIP = NO; 281 | DEBUG_INFORMATION_FORMAT = dwarf; 282 | ENABLE_STRICT_OBJC_MSGSEND = YES; 283 | ENABLE_TESTABILITY = YES; 284 | GCC_C_LANGUAGE_STANDARD = gnu11; 285 | GCC_DYNAMIC_NO_PIC = NO; 286 | GCC_NO_COMMON_BLOCKS = YES; 287 | GCC_OPTIMIZATION_LEVEL = 0; 288 | GCC_PREPROCESSOR_DEFINITIONS = ( 289 | "DEBUG=1", 290 | "$(inherited)", 291 | ); 292 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 293 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 294 | GCC_WARN_UNDECLARED_SELECTOR = YES; 295 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 296 | GCC_WARN_UNUSED_FUNCTION = YES; 297 | GCC_WARN_UNUSED_VARIABLE = YES; 298 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 299 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 300 | MTL_FAST_MATH = YES; 301 | ONLY_ACTIVE_ARCH = YES; 302 | SDKROOT = iphoneos; 303 | }; 304 | name = Debug; 305 | }; 306 | 3CD8D97A23C47DB100993762 /* Release */ = { 307 | isa = XCBuildConfiguration; 308 | buildSettings = { 309 | ALWAYS_SEARCH_USER_PATHS = NO; 310 | CLANG_ANALYZER_NONNULL = YES; 311 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 312 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 313 | CLANG_CXX_LIBRARY = "libc++"; 314 | CLANG_ENABLE_MODULES = YES; 315 | CLANG_ENABLE_OBJC_ARC = YES; 316 | CLANG_ENABLE_OBJC_WEAK = YES; 317 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 318 | CLANG_WARN_BOOL_CONVERSION = YES; 319 | CLANG_WARN_COMMA = YES; 320 | CLANG_WARN_CONSTANT_CONVERSION = YES; 321 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 322 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 323 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 324 | CLANG_WARN_EMPTY_BODY = YES; 325 | CLANG_WARN_ENUM_CONVERSION = YES; 326 | CLANG_WARN_INFINITE_RECURSION = YES; 327 | CLANG_WARN_INT_CONVERSION = YES; 328 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 329 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 330 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 331 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 332 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 333 | CLANG_WARN_STRICT_PROTOTYPES = YES; 334 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 335 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 336 | CLANG_WARN_UNREACHABLE_CODE = YES; 337 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 338 | COPY_PHASE_STRIP = NO; 339 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 340 | ENABLE_NS_ASSERTIONS = NO; 341 | ENABLE_STRICT_OBJC_MSGSEND = YES; 342 | GCC_C_LANGUAGE_STANDARD = gnu11; 343 | GCC_NO_COMMON_BLOCKS = YES; 344 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 345 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 346 | GCC_WARN_UNDECLARED_SELECTOR = YES; 347 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 348 | GCC_WARN_UNUSED_FUNCTION = YES; 349 | GCC_WARN_UNUSED_VARIABLE = YES; 350 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 351 | MTL_ENABLE_DEBUG_INFO = NO; 352 | MTL_FAST_MATH = YES; 353 | SDKROOT = iphoneos; 354 | VALIDATE_PRODUCT = YES; 355 | }; 356 | name = Release; 357 | }; 358 | 3CD8D97C23C47DB100993762 /* Debug */ = { 359 | isa = XCBuildConfiguration; 360 | baseConfigurationReference = A157BAA979FB8BA0E1AC1051 /* Pods-CocopodsCacheProxy-Demo.debug.xcconfig */; 361 | buildSettings = { 362 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 363 | CODE_SIGN_STYLE = Automatic; 364 | INFOPLIST_FILE = "CocopodsCacheProxy-Demo/Info.plist"; 365 | LD_RUNPATH_SEARCH_PATHS = ( 366 | "$(inherited)", 367 | "@executable_path/Frameworks", 368 | ); 369 | PRODUCT_BUNDLE_IDENTIFIER = "com.0x1306a94.CocopodsCacheProxy-Demo"; 370 | PRODUCT_NAME = "$(TARGET_NAME)"; 371 | TARGETED_DEVICE_FAMILY = "1,2"; 372 | }; 373 | name = Debug; 374 | }; 375 | 3CD8D97D23C47DB100993762 /* Release */ = { 376 | isa = XCBuildConfiguration; 377 | baseConfigurationReference = 5ACC61A870B0C068C52BC577 /* Pods-CocopodsCacheProxy-Demo.release.xcconfig */; 378 | buildSettings = { 379 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 380 | CODE_SIGN_STYLE = Automatic; 381 | INFOPLIST_FILE = "CocopodsCacheProxy-Demo/Info.plist"; 382 | LD_RUNPATH_SEARCH_PATHS = ( 383 | "$(inherited)", 384 | "@executable_path/Frameworks", 385 | ); 386 | PRODUCT_BUNDLE_IDENTIFIER = "com.0x1306a94.CocopodsCacheProxy-Demo"; 387 | PRODUCT_NAME = "$(TARGET_NAME)"; 388 | TARGETED_DEVICE_FAMILY = "1,2"; 389 | }; 390 | name = Release; 391 | }; 392 | /* End XCBuildConfiguration section */ 393 | 394 | /* Begin XCConfigurationList section */ 395 | 3CD8D95D23C47DAE00993762 /* Build configuration list for PBXProject "CocopodsCacheProxy-Demo" */ = { 396 | isa = XCConfigurationList; 397 | buildConfigurations = ( 398 | 3CD8D97923C47DB100993762 /* Debug */, 399 | 3CD8D97A23C47DB100993762 /* Release */, 400 | ); 401 | defaultConfigurationIsVisible = 0; 402 | defaultConfigurationName = Release; 403 | }; 404 | 3CD8D97B23C47DB100993762 /* Build configuration list for PBXNativeTarget "CocopodsCacheProxy-Demo" */ = { 405 | isa = XCConfigurationList; 406 | buildConfigurations = ( 407 | 3CD8D97C23C47DB100993762 /* Debug */, 408 | 3CD8D97D23C47DB100993762 /* Release */, 409 | ); 410 | defaultConfigurationIsVisible = 0; 411 | defaultConfigurationName = Release; 412 | }; 413 | /* End XCConfigurationList section */ 414 | }; 415 | rootObject = 3CD8D95A23C47DAE00993762 /* Project object */; 416 | } 417 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CocopodsCacheProxy-Demo 4 | // 5 | // Created by king on 2020/1/7. 6 | // Copyright © 2020 K&K. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CocopodsCacheProxy-Demo 4 | // 5 | // Created by king on 2020/1/7. 6 | // Copyright © 2020 K&K. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | #pragma mark - UISceneSession lifecycle 25 | 26 | 27 | - (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { 28 | // Called when a new scene session is being created. 29 | // Use this method to select a configuration to create the new scene with. 30 | return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; 31 | } 32 | 33 | 34 | - (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions { 35 | // Called when the user discards a scene session. 36 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 37 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 38 | } 39 | 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/SceneDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.h 3 | // CocopodsCacheProxy-Demo 4 | // 5 | // Created by king on 2020/1/7. 6 | // Copyright © 2020 K&K. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SceneDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow * window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/SceneDelegate.m: -------------------------------------------------------------------------------- 1 | #import "SceneDelegate.h" 2 | 3 | @interface SceneDelegate () 4 | 5 | @end 6 | 7 | @implementation SceneDelegate 8 | 9 | 10 | - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { 11 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 12 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 13 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 14 | } 15 | 16 | 17 | - (void)sceneDidDisconnect:(UIScene *)scene { 18 | // Called as the scene is being released by the system. 19 | // This occurs shortly after the scene enters the background, or when its session is discarded. 20 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 21 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 22 | } 23 | 24 | 25 | - (void)sceneDidBecomeActive:(UIScene *)scene { 26 | // Called when the scene has moved from an inactive state to an active state. 27 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 28 | } 29 | 30 | 31 | - (void)sceneWillResignActive:(UIScene *)scene { 32 | // Called when the scene will move from an active state to an inactive state. 33 | // This may occur due to temporary interruptions (ex. an incoming phone call). 34 | } 35 | 36 | 37 | - (void)sceneWillEnterForeground:(UIScene *)scene { 38 | // Called as the scene transitions from the background to the foreground. 39 | // Use this method to undo the changes made on entering the background. 40 | } 41 | 42 | 43 | - (void)sceneDidEnterBackground:(UIScene *)scene { 44 | // Called as the scene transitions from the foreground to the background. 45 | // Use this method to save data, release shared resources, and store enough scene-specific state information 46 | // to restore the scene back to its current state. 47 | } 48 | 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CocopodsCacheProxy-Demo 4 | // 5 | // Created by king on 2020/1/7. 6 | // Copyright © 2020 K&K. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CocopodsCacheProxy-Demo 4 | // 5 | // Created by king on 2020/1/7. 6 | // Copyright © 2020 K&K. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view. 20 | } 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /test-project/CocopodsCacheProxy-Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CocopodsCacheProxy-Demo 4 | // 5 | // Created by king on 2020/1/7. 6 | // Copyright © 2020 K&K. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | NSString * appDelegateClassName; 14 | @autoreleasepool { 15 | // Setup code that might create autoreleased objects goes here. 16 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 17 | } 18 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 19 | } 20 | -------------------------------------------------------------------------------- /test-project/Gemfile: -------------------------------------------------------------------------------- 1 | 2 | gem 'cocoapods' 3 | gem 'cocoapods-cache-proxy', :path => '../' 4 | -------------------------------------------------------------------------------- /test-project/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | cocoapods-cache-proxy (0.0.2) 5 | cocoapods (~> 1.5) 6 | 7 | GEM 8 | specs: 9 | CFPropertyList (3.0.2) 10 | activesupport (4.2.11.1) 11 | i18n (~> 0.7) 12 | minitest (~> 5.1) 13 | thread_safe (~> 0.3, >= 0.3.4) 14 | tzinfo (~> 1.1) 15 | algoliasearch (1.27.1) 16 | httpclient (~> 2.8, >= 2.8.3) 17 | json (>= 1.5.1) 18 | atomos (0.1.3) 19 | claide (1.0.3) 20 | cocoapods (1.8.4) 21 | activesupport (>= 4.0.2, < 5) 22 | claide (>= 1.0.2, < 2.0) 23 | cocoapods-core (= 1.8.4) 24 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 25 | cocoapods-downloader (>= 1.2.2, < 2.0) 26 | cocoapods-plugins (>= 1.0.0, < 2.0) 27 | cocoapods-search (>= 1.0.0, < 2.0) 28 | cocoapods-stats (>= 1.0.0, < 2.0) 29 | cocoapods-trunk (>= 1.4.0, < 2.0) 30 | cocoapods-try (>= 1.1.0, < 2.0) 31 | colored2 (~> 3.1) 32 | escape (~> 0.0.4) 33 | fourflusher (>= 2.3.0, < 3.0) 34 | gh_inspector (~> 1.0) 35 | molinillo (~> 0.6.6) 36 | nap (~> 1.0) 37 | ruby-macho (~> 1.4) 38 | xcodeproj (>= 1.11.1, < 2.0) 39 | cocoapods-core (1.8.4) 40 | activesupport (>= 4.0.2, < 6) 41 | algoliasearch (~> 1.0) 42 | concurrent-ruby (~> 1.1) 43 | fuzzy_match (~> 2.0.4) 44 | nap (~> 1.0) 45 | cocoapods-deintegrate (1.0.4) 46 | cocoapods-downloader (1.3.0) 47 | cocoapods-plugins (1.0.0) 48 | nap 49 | cocoapods-search (1.0.0) 50 | cocoapods-stats (1.1.0) 51 | cocoapods-trunk (1.4.1) 52 | nap (>= 0.8, < 2.0) 53 | netrc (~> 0.11) 54 | cocoapods-try (1.1.0) 55 | colored2 (3.1.2) 56 | concurrent-ruby (1.1.5) 57 | escape (0.0.4) 58 | fourflusher (2.3.1) 59 | fuzzy_match (2.0.4) 60 | gh_inspector (1.1.3) 61 | httpclient (2.8.3) 62 | i18n (0.9.5) 63 | concurrent-ruby (~> 1.0) 64 | json (2.3.0) 65 | minitest (5.13.0) 66 | molinillo (0.6.6) 67 | nanaimo (0.2.6) 68 | nap (1.1.0) 69 | netrc (0.11.0) 70 | ruby-macho (1.4.0) 71 | thread_safe (0.3.6) 72 | tzinfo (1.2.6) 73 | thread_safe (~> 0.1) 74 | xcodeproj (1.14.0) 75 | CFPropertyList (>= 2.3.3, < 4.0) 76 | atomos (~> 0.1.3) 77 | claide (>= 1.0.2, < 2.0) 78 | colored2 (~> 3.1) 79 | nanaimo (~> 0.2.6) 80 | 81 | PLATFORMS 82 | ruby 83 | 84 | DEPENDENCIES 85 | cocoapods 86 | cocoapods-cache-proxy! 87 | 88 | BUNDLED WITH 89 | 2.1.4 90 | -------------------------------------------------------------------------------- /test-project/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | plugin "cocoapods-cache-proxy", :proxy => "TestProxy" 5 | 6 | target 'CocopodsCacheProxy-Demo' do 7 | # Comment the next line if you don't want to use dynamic frameworks 8 | use_frameworks! 9 | pod 'AFNetworking', :ignore_cache_proxy => false 10 | pod 'SDWebImage', :cache_proxy_source => 'Test' 11 | pod 'RxSwift', :cache_proxy_source => 'Test' 12 | pod 'RxCocoa', :cache_proxy_source => 'Test' 13 | pod 'SnapKit' 14 | pod 'YYText' 15 | pod 'YYModel' 16 | # Pods for CocopodsCacheProxy-Demo 17 | 18 | end 19 | -------------------------------------------------------------------------------- /test-project/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (3.2.1): 3 | - AFNetworking/NSURLSession (= 3.2.1) 4 | - AFNetworking/Reachability (= 3.2.1) 5 | - AFNetworking/Security (= 3.2.1) 6 | - AFNetworking/Serialization (= 3.2.1) 7 | - AFNetworking/UIKit (= 3.2.1) 8 | - AFNetworking/NSURLSession (3.2.1): 9 | - AFNetworking/Reachability 10 | - AFNetworking/Security 11 | - AFNetworking/Serialization 12 | - AFNetworking/Reachability (3.2.1) 13 | - AFNetworking/Security (3.2.1) 14 | - AFNetworking/Serialization (3.2.1) 15 | - AFNetworking/UIKit (3.2.1): 16 | - AFNetworking/NSURLSession 17 | - RxCocoa (5.0.1): 18 | - RxRelay (~> 5) 19 | - RxSwift (~> 5) 20 | - RxRelay (5.0.1): 21 | - RxSwift (~> 5) 22 | - RxSwift (5.0.1) 23 | - SDWebImage (5.4.2): 24 | - SDWebImage/Core (= 5.4.2) 25 | - SDWebImage/Core (5.4.2) 26 | - SnapKit (5.0.1) 27 | - YYModel (1.0.4) 28 | - YYText (1.0.7) 29 | 30 | DEPENDENCIES: 31 | - AFNetworking 32 | - RxCocoa 33 | - RxSwift 34 | - SDWebImage 35 | - SnapKit 36 | - YYModel 37 | - YYText 38 | 39 | SPEC REPOS: 40 | trunk: 41 | - AFNetworking 42 | - RxCocoa 43 | - RxRelay 44 | - RxSwift 45 | - SDWebImage 46 | - SnapKit 47 | - YYModel 48 | - YYText 49 | 50 | SPEC CHECKSUMS: 51 | AFNetworking: b6f891fdfaed196b46c7a83cf209e09697b94057 52 | RxCocoa: e741b9749968e8a143e2b787f1dfbff2b63d0a5c 53 | RxRelay: 89d54507f4fd4d969e6ec1d4bd7f3673640b4640 54 | RxSwift: e2dc62b366a3adf6a0be44ba9f405efd4c94e0c4 55 | SDWebImage: 4ca2dc4eefae4224bea8f504251cda485a363745 56 | SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb 57 | YYModel: 2a7fdd96aaa4b86a824e26d0c517de8928c04b30 58 | YYText: 5c461d709e24d55a182d1441c41dc639a18a4849 59 | 60 | PODFILE CHECKSUM: be21be48ec4cd5b98aeb21978a1a959a33b015ee 61 | 62 | COCOAPODS: 1.8.4 63 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -ex 4 | 5 | gem build cocoapods-cache-proxy.gemspec && gem install cocoapods-cache-proxy-0.0.2.gem --verbose --------------------------------------------------------------------------------