xcocoapods 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +6303 -0
  3. data/LICENSE +28 -0
  4. data/README.md +80 -0
  5. data/bin/pod +56 -0
  6. data/bin/sandbox-pod +168 -0
  7. data/lib/cocoapods.rb +73 -0
  8. data/lib/cocoapods/command.rb +175 -0
  9. data/lib/cocoapods/command/cache.rb +28 -0
  10. data/lib/cocoapods/command/cache/clean.rb +90 -0
  11. data/lib/cocoapods/command/cache/list.rb +69 -0
  12. data/lib/cocoapods/command/env.rb +66 -0
  13. data/lib/cocoapods/command/init.rb +128 -0
  14. data/lib/cocoapods/command/install.rb +45 -0
  15. data/lib/cocoapods/command/ipc.rb +19 -0
  16. data/lib/cocoapods/command/ipc/list.rb +40 -0
  17. data/lib/cocoapods/command/ipc/podfile.rb +31 -0
  18. data/lib/cocoapods/command/ipc/podfile_json.rb +30 -0
  19. data/lib/cocoapods/command/ipc/repl.rb +51 -0
  20. data/lib/cocoapods/command/ipc/spec.rb +29 -0
  21. data/lib/cocoapods/command/ipc/update_search_index.rb +24 -0
  22. data/lib/cocoapods/command/lib.rb +11 -0
  23. data/lib/cocoapods/command/lib/create.rb +105 -0
  24. data/lib/cocoapods/command/lib/lint.rb +121 -0
  25. data/lib/cocoapods/command/list.rb +39 -0
  26. data/lib/cocoapods/command/options/project_directory.rb +36 -0
  27. data/lib/cocoapods/command/options/repo_update.rb +34 -0
  28. data/lib/cocoapods/command/outdated.rb +140 -0
  29. data/lib/cocoapods/command/repo.rb +29 -0
  30. data/lib/cocoapods/command/repo/add.rb +103 -0
  31. data/lib/cocoapods/command/repo/lint.rb +82 -0
  32. data/lib/cocoapods/command/repo/list.rb +93 -0
  33. data/lib/cocoapods/command/repo/push.rb +281 -0
  34. data/lib/cocoapods/command/repo/remove.rb +36 -0
  35. data/lib/cocoapods/command/repo/update.rb +28 -0
  36. data/lib/cocoapods/command/setup.rb +103 -0
  37. data/lib/cocoapods/command/spec.rb +112 -0
  38. data/lib/cocoapods/command/spec/cat.rb +51 -0
  39. data/lib/cocoapods/command/spec/create.rb +283 -0
  40. data/lib/cocoapods/command/spec/edit.rb +87 -0
  41. data/lib/cocoapods/command/spec/env_spec.rb +53 -0
  42. data/lib/cocoapods/command/spec/lint.rb +137 -0
  43. data/lib/cocoapods/command/spec/which.rb +43 -0
  44. data/lib/cocoapods/command/update.rb +101 -0
  45. data/lib/cocoapods/config.rb +347 -0
  46. data/lib/cocoapods/core_overrides.rb +1 -0
  47. data/lib/cocoapods/downloader.rb +190 -0
  48. data/lib/cocoapods/downloader/cache.rb +233 -0
  49. data/lib/cocoapods/downloader/request.rb +86 -0
  50. data/lib/cocoapods/downloader/response.rb +16 -0
  51. data/lib/cocoapods/executable.rb +222 -0
  52. data/lib/cocoapods/external_sources.rb +57 -0
  53. data/lib/cocoapods/external_sources/abstract_external_source.rb +205 -0
  54. data/lib/cocoapods/external_sources/downloader_source.rb +30 -0
  55. data/lib/cocoapods/external_sources/path_source.rb +55 -0
  56. data/lib/cocoapods/external_sources/podspec_source.rb +54 -0
  57. data/lib/cocoapods/gem_version.rb +5 -0
  58. data/lib/cocoapods/generator/acknowledgements.rb +107 -0
  59. data/lib/cocoapods/generator/acknowledgements/markdown.rb +44 -0
  60. data/lib/cocoapods/generator/acknowledgements/plist.rb +94 -0
  61. data/lib/cocoapods/generator/app_target_helper.rb +244 -0
  62. data/lib/cocoapods/generator/bridge_support.rb +22 -0
  63. data/lib/cocoapods/generator/constant.rb +19 -0
  64. data/lib/cocoapods/generator/copy_resources_script.rb +230 -0
  65. data/lib/cocoapods/generator/dummy_source.rb +31 -0
  66. data/lib/cocoapods/generator/embed_frameworks_script.rb +215 -0
  67. data/lib/cocoapods/generator/header.rb +103 -0
  68. data/lib/cocoapods/generator/info_plist_file.rb +116 -0
  69. data/lib/cocoapods/generator/module_map.rb +99 -0
  70. data/lib/cocoapods/generator/prefix_header.rb +60 -0
  71. data/lib/cocoapods/generator/umbrella_header.rb +46 -0
  72. data/lib/cocoapods/hooks_manager.rb +132 -0
  73. data/lib/cocoapods/installer.rb +703 -0
  74. data/lib/cocoapods/installer/analyzer.rb +972 -0
  75. data/lib/cocoapods/installer/analyzer/analysis_result.rb +87 -0
  76. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +98 -0
  77. data/lib/cocoapods/installer/analyzer/pod_variant.rb +67 -0
  78. data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +157 -0
  79. data/lib/cocoapods/installer/analyzer/podfile_dependency_cache.rb +54 -0
  80. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +240 -0
  81. data/lib/cocoapods/installer/analyzer/specs_state.rb +84 -0
  82. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +53 -0
  83. data/lib/cocoapods/installer/analyzer/target_inspector.rb +260 -0
  84. data/lib/cocoapods/installer/installation_options.rb +158 -0
  85. data/lib/cocoapods/installer/pod_source_installer.rb +202 -0
  86. data/lib/cocoapods/installer/pod_source_preparer.rb +77 -0
  87. data/lib/cocoapods/installer/podfile_validator.rb +139 -0
  88. data/lib/cocoapods/installer/post_install_hooks_context.rb +132 -0
  89. data/lib/cocoapods/installer/pre_install_hooks_context.rb +51 -0
  90. data/lib/cocoapods/installer/source_provider_hooks_context.rb +34 -0
  91. data/lib/cocoapods/installer/user_project_integrator.rb +250 -0
  92. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +463 -0
  93. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +146 -0
  94. data/lib/cocoapods/installer/xcode.rb +8 -0
  95. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +416 -0
  96. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +181 -0
  97. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +84 -0
  98. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +334 -0
  99. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +777 -0
  100. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +116 -0
  101. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +86 -0
  102. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +256 -0
  103. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +68 -0
  104. data/lib/cocoapods/installer/xcode/target_validator.rb +147 -0
  105. data/lib/cocoapods/open-uri.rb +33 -0
  106. data/lib/cocoapods/project.rb +414 -0
  107. data/lib/cocoapods/resolver.rb +585 -0
  108. data/lib/cocoapods/resolver/lazy_specification.rb +79 -0
  109. data/lib/cocoapods/sandbox.rb +404 -0
  110. data/lib/cocoapods/sandbox/file_accessor.rb +444 -0
  111. data/lib/cocoapods/sandbox/headers_store.rb +146 -0
  112. data/lib/cocoapods/sandbox/path_list.rb +220 -0
  113. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +85 -0
  114. data/lib/cocoapods/sandbox/podspec_finder.rb +23 -0
  115. data/lib/cocoapods/sources_manager.rb +157 -0
  116. data/lib/cocoapods/target.rb +261 -0
  117. data/lib/cocoapods/target/aggregate_target.rb +338 -0
  118. data/lib/cocoapods/target/build_settings.rb +1075 -0
  119. data/lib/cocoapods/target/pod_target.rb +559 -0
  120. data/lib/cocoapods/user_interface.rb +459 -0
  121. data/lib/cocoapods/user_interface/error_report.rb +187 -0
  122. data/lib/cocoapods/user_interface/inspector_reporter.rb +109 -0
  123. data/lib/cocoapods/validator.rb +981 -0
  124. metadata +533 -0
@@ -0,0 +1,53 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ module Pod
4
+ describe Command::Env do
5
+ describe 'In general' do
6
+ before do
7
+ @report = Command::Env
8
+ end
9
+
10
+ it 'returns a well-structured environment report' do
11
+ expected = <<-EOS
12
+
13
+ ### Stack
14
+
15
+ ```
16
+ CocoaPods : #{Pod::VERSION}
17
+ Ruby : #{RUBY_DESCRIPTION}
18
+ RubyGems : #{Gem::VERSION}
19
+ Host : :host_information
20
+ Xcode : :xcode_information
21
+ Git : :git_information
22
+ Ruby lib dir : #{RbConfig::CONFIG['libdir']}
23
+ Repositories : repo_1
24
+ repo_2
25
+ ```
26
+
27
+ ### Installation Source
28
+
29
+ ```
30
+ Executable Path: /usr/bin/command
31
+ ```
32
+
33
+ ### Plugins
34
+
35
+ ```
36
+ cocoapods : #{Pod::VERSION}
37
+ cocoapods-core : #{Pod::VERSION}
38
+ cocoapods-plugins : 1.2.3
39
+ ```
40
+
41
+ ### Podfile
42
+
43
+ ```ruby
44
+
45
+ ```
46
+ EOS
47
+
48
+ @report.stubs(:actual_path).returns('/usr/bin/command')
49
+ report.should == expected
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,137 @@
1
+ module Pod
2
+ class Command
3
+ class Spec < Command
4
+ class Lint < Spec
5
+ self.summary = 'Validates a spec file'
6
+
7
+ self.description = <<-DESC
8
+ Validates `NAME.podspec`. If a `DIRECTORY` is provided, it validates
9
+ the podspec files found, including subfolders. In case
10
+ the argument is omitted, it defaults to the current working dir.
11
+ DESC
12
+
13
+ self.arguments = [
14
+ CLAide::Argument.new(%w(NAME.podspec DIRECTORY http://PATH/NAME.podspec), false, true),
15
+ ]
16
+
17
+ def self.options
18
+ [
19
+ ['--quick', 'Lint skips checks that would require to download and build the spec'],
20
+ ['--allow-warnings', 'Lint validates even if warnings are present'],
21
+ ['--subspec=NAME', 'Lint validates only the given subspec'],
22
+ ['--no-subspecs', 'Lint skips validation of subspecs'],
23
+ ['--no-clean', 'Lint leaves the build directory intact for inspection'],
24
+ ['--fail-fast', 'Lint stops on the first failing platform or subspec'],
25
+ ['--use-libraries', 'Lint uses static libraries to install the spec'],
26
+ ['--sources=https://github.com/artsy/Specs,master', 'The sources from which to pull dependent pods ' \
27
+ '(defaults to https://github.com/CocoaPods/Specs.git). ' \
28
+ 'Multiple sources must be comma-delimited.'],
29
+ ['--platforms=ios,macos', 'Lint against specific platforms' \
30
+ '(defaults to all platforms supported by the podspec).' \
31
+ 'Multiple platforms must be comma-delimited'],
32
+ ['--private', 'Lint skips checks that apply only to public specs'],
33
+ ['--swift-version=VERSION', 'The SWIFT_VERSION that should be used to lint the spec. ' \
34
+ 'This takes precedence over a .swift-version file.'],
35
+ ['--skip-import-validation', 'Lint skips validating that the pod can be imported'],
36
+ ['--skip-tests', 'Lint skips building and running tests during validation'],
37
+ ].concat(super)
38
+ end
39
+
40
+ def initialize(argv)
41
+ @quick = argv.flag?('quick')
42
+ @allow_warnings = argv.flag?('allow-warnings')
43
+ @clean = argv.flag?('clean', true)
44
+ @fail_fast = argv.flag?('fail-fast', false)
45
+ @subspecs = argv.flag?('subspecs', true)
46
+ @only_subspec = argv.option('subspec')
47
+ @use_frameworks = !argv.flag?('use-libraries')
48
+ @source_urls = argv.option('sources', 'https://github.com/CocoaPods/Specs.git').split(',')
49
+ @platforms = argv.option('platforms', '').split(',')
50
+ @private = argv.flag?('private', false)
51
+ @swift_version = argv.option('swift-version', nil)
52
+ @skip_import_validation = argv.flag?('skip-import-validation', false)
53
+ @skip_tests = argv.flag?('skip-tests', false)
54
+ @podspecs_paths = argv.arguments!
55
+ super
56
+ end
57
+
58
+ def run
59
+ UI.puts
60
+ failure_reasons = []
61
+ podspecs_to_lint.each do |podspec|
62
+ validator = Validator.new(podspec, @source_urls, @platforms)
63
+ validator.quick = @quick
64
+ validator.no_clean = !@clean
65
+ validator.fail_fast = @fail_fast
66
+ validator.allow_warnings = @allow_warnings
67
+ validator.no_subspecs = !@subspecs || @only_subspec
68
+ validator.only_subspec = @only_subspec
69
+ validator.use_frameworks = @use_frameworks
70
+ validator.ignore_public_only_results = @private
71
+ validator.swift_version = @swift_version
72
+ validator.skip_import_validation = @skip_import_validation
73
+ validator.skip_tests = @skip_tests
74
+ validator.validate
75
+ failure_reasons << validator.failure_reason
76
+
77
+ unless @clean
78
+ UI.puts "Pods workspace available at `#{validator.validation_dir}/App.xcworkspace` for inspection."
79
+ UI.puts
80
+ end
81
+ end
82
+
83
+ count = podspecs_to_lint.count
84
+ UI.puts "Analyzed #{count} #{'podspec'.pluralize(count)}.\n\n"
85
+
86
+ failure_reasons.compact!
87
+ if failure_reasons.empty?
88
+ lint_passed_message = count == 1 ? "#{podspecs_to_lint.first.basename} passed validation." : 'All the specs passed validation.'
89
+ UI.puts lint_passed_message.green << "\n\n"
90
+ else
91
+ raise Informative, if count == 1
92
+ "The spec did not pass validation, due to #{failure_reasons.first}."
93
+ else
94
+ "#{failure_reasons.count} out of #{count} specs failed validation."
95
+ end
96
+ end
97
+ podspecs_tmp_dir.rmtree if podspecs_tmp_dir.exist?
98
+ end
99
+
100
+ private
101
+
102
+ def podspecs_to_lint
103
+ @podspecs_to_lint ||= begin
104
+ files = []
105
+ @podspecs_paths << '.' if @podspecs_paths.empty?
106
+ @podspecs_paths.each do |path|
107
+ if path =~ %r{https?://}
108
+ require 'cocoapods/open-uri'
109
+ output_path = podspecs_tmp_dir + File.basename(path)
110
+ output_path.dirname.mkpath
111
+ begin
112
+ open(path) do |io|
113
+ output_path.open('w') { |f| f << io.read }
114
+ end
115
+ rescue => e
116
+ raise Informative, "Downloading a podspec from `#{path}` failed: #{e}"
117
+ end
118
+ files << output_path
119
+ elsif (pathname = Pathname.new(path)).directory?
120
+ files += Pathname.glob(pathname + '*.podspec{.json,}')
121
+ raise Informative, 'No specs found in the current directory.' if files.empty?
122
+ else
123
+ files << (pathname = Pathname.new(path))
124
+ raise Informative, "Unable to find a spec named `#{path}'." unless pathname.exist? && path.include?('.podspec')
125
+ end
126
+ end
127
+ files
128
+ end
129
+ end
130
+
131
+ def podspecs_tmp_dir
132
+ Pathname.new(Dir.tmpdir) + 'CocoaPods/Lint_podspec'
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,43 @@
1
+ module Pod
2
+ class Command
3
+ class Spec < Command
4
+ class Which < Spec
5
+ self.summary = 'Prints the path of the given spec'
6
+
7
+ self.description = <<-DESC
8
+ Prints the path of the .podspec file(s) whose name matches `QUERY`
9
+ DESC
10
+
11
+ self.arguments = [
12
+ CLAide::Argument.new('QUERY', false),
13
+ ]
14
+
15
+ def self.options
16
+ [
17
+ ['--regex', 'Interpret the `QUERY` as a regular expression'],
18
+ ['--show-all', 'Print all versions of the given podspec'],
19
+ ].concat(super)
20
+ end
21
+
22
+ def initialize(argv)
23
+ @use_regex = argv.flag?('regex')
24
+ @show_all = argv.flag?('show-all')
25
+ @query = argv.shift_argument
26
+ @query = @query.gsub('.podspec', '') unless @query.nil?
27
+ super
28
+ end
29
+
30
+ def validate!
31
+ super
32
+ help! 'A podspec name is required.' unless @query
33
+ validate_regex!(@query) if @use_regex
34
+ end
35
+
36
+ def run
37
+ query = @use_regex ? @query : Regexp.escape(@query)
38
+ UI.puts get_path_of_spec(query, @show_all)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,101 @@
1
+ module Pod
2
+ class Command
3
+ class Update < Command
4
+ include RepoUpdate
5
+ include ProjectDirectory
6
+
7
+ self.summary = 'Update outdated project dependencies and create new ' \
8
+ 'Podfile.lock'
9
+
10
+ self.description = <<-DESC
11
+ Updates the Pods identified by the specified `POD_NAMES`, which is a
12
+ space-delimited list of pod names. If no `POD_NAMES` are specified, it
13
+ updates all the Pods, ignoring the contents of the Podfile.lock. This
14
+ command is reserved for the update of dependencies; pod install should
15
+ be used to install changes to the Podfile.
16
+ DESC
17
+
18
+ self.arguments = [
19
+ CLAide::Argument.new('POD_NAMES', false, true),
20
+ ]
21
+
22
+ def self.options
23
+ [
24
+ ['--sources=https://github.com/artsy/Specs,master', 'The sources from which to update dependent pods. ' \
25
+ 'Multiple sources must be comma-delimited. The master repo will not be included by default with this option.'],
26
+ ['--exclude-pods=podName', 'Pods to exclude during update. Multiple pods must be comma-delimited.'],
27
+ ].concat(super)
28
+ end
29
+
30
+ def initialize(argv)
31
+ @pods = argv.arguments! unless argv.arguments.empty?
32
+
33
+ source_urls = argv.option('sources', '').split(',')
34
+ excluded_pods = argv.option('exclude-pods', '').split(',')
35
+ unless source_urls.empty?
36
+ source_pods = source_urls.flat_map { |url| config.sources_manager.source_with_name_or_url(url).pods }
37
+ unless source_pods.empty?
38
+ source_pods = source_pods.select { |pod| config.lockfile.pod_names.include?(pod) }
39
+ if @pods
40
+ @pods += source_pods
41
+ else
42
+ @pods = source_pods unless source_pods.empty?
43
+ end
44
+ end
45
+ end
46
+
47
+ unless excluded_pods.empty?
48
+ @pods ||= config.lockfile.pod_names.dup
49
+
50
+ non_installed_pods = (excluded_pods - @pods)
51
+ unless non_installed_pods.empty?
52
+ pluralized_words = non_installed_pods.length > 1 ? %w(Pods are) : %w(Pod is)
53
+ message = "Trying to skip `#{non_installed_pods.join('`, `')}` #{pluralized_words.first} " \
54
+ "which #{pluralized_words.last} not installed"
55
+ raise Informative, message
56
+ end
57
+
58
+ @pods.delete_if { |pod| excluded_pods.include?(pod) }
59
+ end
60
+
61
+ super
62
+ end
63
+
64
+ # Check if all given pods are installed
65
+ #
66
+ def verify_pods_are_installed!
67
+ lockfile_roots = config.lockfile.pod_names.map { |p| Specification.root_name(p) }
68
+ missing_pods = @pods.map { |p| Specification.root_name(p) }.select do |pod|
69
+ !lockfile_roots.include?(pod)
70
+ end
71
+
72
+ unless missing_pods.empty?
73
+ message = if missing_pods.length > 1
74
+ "Pods `#{missing_pods.join('`, `')}` are not " \
75
+ 'installed and cannot be updated'
76
+ else
77
+ "The `#{missing_pods.first}` Pod is not installed " \
78
+ 'and cannot be updated'
79
+ end
80
+ raise Informative, message
81
+ end
82
+ end
83
+
84
+ def run
85
+ verify_podfile_exists!
86
+
87
+ installer = installer_for_config
88
+ installer.repo_update = repo_update?(:default => true)
89
+ if @pods
90
+ verify_lockfile_exists!
91
+ verify_pods_are_installed!
92
+ installer.update = { :pods => @pods }
93
+ else
94
+ UI.puts 'Update all pods'.yellow
95
+ installer.update = true
96
+ end
97
+ installer.install!
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,347 @@
1
+ require 'active_support/multibyte/unicode'
2
+
3
+ module Pod
4
+ # Stores the global configuration of CocoaPods.
5
+ #
6
+ class Config
7
+ # The default settings for the configuration.
8
+ #
9
+ # Users can specify custom settings in `~/.cocoapods/config.yaml`.
10
+ # An example of the contents of this file might look like:
11
+ #
12
+ # ---
13
+ # skip_repo_update: true
14
+ # new_version_message: false
15
+ #
16
+ DEFAULTS = {
17
+ :verbose => false,
18
+ :silent => false,
19
+ :skip_download_cache => !ENV['COCOAPODS_SKIP_CACHE'].nil?,
20
+
21
+ :new_version_message => ENV['COCOAPODS_SKIP_UPDATE_MESSAGE'].nil?,
22
+
23
+ :cache_root => Pathname.new(Dir.home) + 'Library/Caches/CocoaPods',
24
+ }
25
+
26
+ # Applies the given changes to the config for the duration of the given
27
+ # block.
28
+ #
29
+ # @param [Hash<#to_sym,Object>] changes
30
+ # the changes to merge temporarily with the current config
31
+ #
32
+ # @yield [] is called while the changes are applied
33
+ #
34
+ def with_changes(changes)
35
+ old = {}
36
+ changes.keys.each do |key|
37
+ key = key.to_sym
38
+ old[key] = send(key) if respond_to?(key)
39
+ end
40
+ configure_with(changes)
41
+ yield if block_given?
42
+ ensure
43
+ configure_with(old)
44
+ end
45
+
46
+ public
47
+
48
+ #-------------------------------------------------------------------------#
49
+
50
+ # @!group UI
51
+
52
+ # @return [Bool] Whether CocoaPods should provide detailed output about the
53
+ # performed actions.
54
+ #
55
+ attr_accessor :verbose
56
+ alias_method :verbose?, :verbose
57
+
58
+ # @return [Bool] Whether CocoaPods should produce not output.
59
+ #
60
+ attr_accessor :silent
61
+ alias_method :silent?, :silent
62
+
63
+ # @return [Bool] Whether a message should be printed when a new version of
64
+ # CocoaPods is available.
65
+ #
66
+ attr_accessor :new_version_message
67
+ alias_method :new_version_message?, :new_version_message
68
+
69
+ #-------------------------------------------------------------------------#
70
+
71
+ # @!group Installation
72
+
73
+ # @return [Bool] Whether the installer should skip the download cache.
74
+ #
75
+ attr_accessor :skip_download_cache
76
+ alias_method :skip_download_cache?, :skip_download_cache
77
+
78
+ public
79
+
80
+ #-------------------------------------------------------------------------#
81
+
82
+ # @!group Cache
83
+
84
+ # @return [Pathname] The directory where CocoaPods should cache remote data
85
+ # and other expensive to compute information.
86
+ #
87
+ attr_accessor :cache_root
88
+
89
+ def cache_root
90
+ @cache_root.mkpath unless @cache_root.exist?
91
+ @cache_root
92
+ end
93
+
94
+ public
95
+
96
+ #-------------------------------------------------------------------------#
97
+
98
+ # @!group Initialization
99
+
100
+ def initialize(use_user_settings = true)
101
+ configure_with(DEFAULTS)
102
+
103
+ unless ENV['CP_HOME_DIR'].nil?
104
+ @cache_root = home_dir + 'cache'
105
+ end
106
+
107
+ if use_user_settings && user_settings_file.exist?
108
+ require 'yaml'
109
+ user_settings = YAML.load_file(user_settings_file)
110
+ configure_with(user_settings)
111
+ end
112
+
113
+ unless ENV['CP_CACHE_DIR'].nil?
114
+ @cache_root = Pathname.new(ENV['CP_CACHE_DIR']).expand_path
115
+ end
116
+ end
117
+
118
+ def verbose
119
+ @verbose && !silent
120
+ end
121
+
122
+ public
123
+
124
+ #-------------------------------------------------------------------------#
125
+
126
+ # @!group Paths
127
+
128
+ # @return [Pathname] the directory where repos, templates and configuration
129
+ # files are stored.
130
+ #
131
+ def home_dir
132
+ @home_dir ||= Pathname.new(ENV['CP_HOME_DIR'] || '~/.cocoapods').expand_path
133
+ end
134
+
135
+ # @return [Pathname] the directory where the CocoaPods sources are stored.
136
+ #
137
+ def repos_dir
138
+ @repos_dir ||= Pathname.new(ENV['CP_REPOS_DIR'] || (home_dir + 'repos')).expand_path
139
+ end
140
+
141
+ attr_writer :repos_dir
142
+
143
+ def sources_manager
144
+ return @sources_manager if @sources_manager && @sources_manager.repos_dir == repos_dir
145
+ @sources_manager = Source::Manager.new(repos_dir)
146
+ end
147
+
148
+ # @return [Pathname] the directory where the CocoaPods templates are stored.
149
+ #
150
+ def templates_dir
151
+ @templates_dir ||= Pathname.new(ENV['CP_TEMPLATES_DIR'] || (home_dir + 'templates')).expand_path
152
+ end
153
+
154
+ # @return [Pathname] the root of the CocoaPods installation where the
155
+ # Podfile is located.
156
+ #
157
+ def installation_root
158
+ current_dir = ActiveSupport::Multibyte::Unicode.normalize(Dir.pwd)
159
+ current_path = Pathname.new(current_dir)
160
+ unless @installation_root
161
+ until current_path.root?
162
+ if podfile_path_in_dir(current_path)
163
+ @installation_root = current_path
164
+ unless current_path == Pathname.pwd
165
+ UI.puts("[in #{current_path}]")
166
+ end
167
+ break
168
+ else
169
+ current_path = current_path.parent
170
+ end
171
+ end
172
+ @installation_root ||= Pathname.pwd
173
+ end
174
+ @installation_root
175
+ end
176
+
177
+ attr_writer :installation_root
178
+ alias_method :project_root, :installation_root
179
+
180
+ # @return [Pathname] The root of the sandbox.
181
+ #
182
+ def sandbox_root
183
+ @sandbox_root ||= installation_root + 'Pods'
184
+ end
185
+
186
+ attr_writer :sandbox_root
187
+ alias_method :project_pods_root, :sandbox_root
188
+
189
+ # @return [Sandbox] The sandbox of the current project.
190
+ #
191
+ def sandbox
192
+ @sandbox ||= Sandbox.new(sandbox_root)
193
+ end
194
+
195
+ # @return [Podfile] The Podfile to use for the current execution.
196
+ # @return [Nil] If no Podfile is available.
197
+ #
198
+ def podfile
199
+ @podfile ||= Podfile.from_file(podfile_path) if podfile_path
200
+ end
201
+ attr_writer :podfile
202
+
203
+ # @return [Lockfile] The Lockfile to use for the current execution.
204
+ # @return [Nil] If no Lockfile is available.
205
+ #
206
+ def lockfile
207
+ @lockfile ||= Lockfile.from_file(lockfile_path) if lockfile_path
208
+ end
209
+
210
+ # Returns the path of the Podfile.
211
+ #
212
+ # @note The Podfile can be named either `CocoaPods.podfile.yaml`,
213
+ # `CocoaPods.podfile` or `Podfile`. The first two are preferred as
214
+ # they allow to specify an OS X UTI.
215
+ #
216
+ # @return [Pathname]
217
+ # @return [Nil]
218
+ #
219
+ def podfile_path
220
+ @podfile_path ||= podfile_path_in_dir(installation_root)
221
+ end
222
+
223
+ # Returns the path of the Lockfile.
224
+ #
225
+ # @note The Lockfile is named `Podfile.lock`.
226
+ #
227
+ def lockfile_path
228
+ @lockfile_path ||= installation_root + 'Podfile.lock'
229
+ end
230
+
231
+ # Returns the path of the default Podfile pods.
232
+ #
233
+ # @note The file is expected to be named Podfile.default
234
+ #
235
+ # @return [Pathname]
236
+ #
237
+ def default_podfile_path
238
+ @default_podfile_path ||= templates_dir + 'Podfile.default'
239
+ end
240
+
241
+ # Returns the path of the default Podfile test pods.
242
+ #
243
+ # @note The file is expected to be named Podfile.test
244
+ #
245
+ # @return [Pathname]
246
+ #
247
+ def default_test_podfile_path
248
+ @default_test_podfile_path ||= templates_dir + 'Podfile.test'
249
+ end
250
+
251
+ # @return [Pathname] The file to use to cache the search data.
252
+ #
253
+ def search_index_file
254
+ cache_root + 'search_index.json'
255
+ end
256
+
257
+ private
258
+
259
+ #-------------------------------------------------------------------------#
260
+
261
+ # @!group Private helpers
262
+
263
+ # @return [Pathname] The path of the file which contains the user settings.
264
+ #
265
+ def user_settings_file
266
+ home_dir + 'config.yaml'
267
+ end
268
+
269
+ # Sets the values of the attributes with the given hash.
270
+ #
271
+ # @param [Hash{String,Symbol => Object}] values_by_key
272
+ # The values of the attributes grouped by key.
273
+ #
274
+ # @return [void]
275
+ #
276
+ def configure_with(values_by_key)
277
+ return unless values_by_key
278
+ values_by_key.each do |key, value|
279
+ if key == :cache_root
280
+ value = Pathname.new(value).expand_path
281
+ end
282
+ instance_variable_set("@#{key}", value)
283
+ end
284
+ end
285
+
286
+ # @return [Array<String>] The filenames that the Podfile can have ordered
287
+ # by priority.
288
+ #
289
+ PODFILE_NAMES = [
290
+ 'CocoaPods.podfile.yaml',
291
+ 'CocoaPods.podfile',
292
+ 'Podfile',
293
+ ].freeze
294
+
295
+ public
296
+
297
+ # Returns the path of the Podfile in the given dir if any exists.
298
+ #
299
+ # @param [Pathname] dir
300
+ # The directory where to look for the Podfile.
301
+ #
302
+ # @return [Pathname] The path of the Podfile.
303
+ # @return [Nil] If not Podfile was found in the given dir
304
+ #
305
+ def podfile_path_in_dir(dir)
306
+ PODFILE_NAMES.each do |filename|
307
+ candidate = dir + filename
308
+ if candidate.exist?
309
+ return candidate
310
+ end
311
+ end
312
+ nil
313
+ end
314
+
315
+ public
316
+
317
+ #-------------------------------------------------------------------------#
318
+
319
+ # @!group Singleton
320
+
321
+ # @return [Config] the current config instance creating one if needed.
322
+ #
323
+ def self.instance
324
+ @instance ||= new
325
+ end
326
+
327
+ # Sets the current config instance. If set to nil the config will be
328
+ # recreated when needed.
329
+ #
330
+ # @param [Config, Nil] the instance.
331
+ #
332
+ # @return [void]
333
+ #
334
+ class << self
335
+ attr_writer :instance
336
+ end
337
+
338
+ # Provides support for accessing the configuration instance in other
339
+ # scopes.
340
+ #
341
+ module Mixin
342
+ def config
343
+ Config.instance
344
+ end
345
+ end
346
+ end
347
+ end