cocoapods-binary-cache 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cocoapods-binary-cache/cache/validator.rb +1 -2
  3. data/lib/cocoapods-binary-cache/cache/validator_base.rb +28 -8
  4. data/lib/cocoapods-binary-cache/cache/validator_dev_pods.rb +21 -13
  5. data/lib/cocoapods-binary-cache/cache/validator_non_dev_pods.rb +1 -1
  6. data/lib/cocoapods-binary-cache/diagnosis/base.rb +13 -0
  7. data/lib/cocoapods-binary-cache/diagnosis/diagnosis.rb +16 -0
  8. data/lib/cocoapods-binary-cache/diagnosis/integration.rb +19 -0
  9. data/lib/cocoapods-binary-cache/env.rb +32 -0
  10. data/lib/cocoapods-binary-cache/helper/lockfile.rb +26 -3
  11. data/lib/cocoapods-binary-cache/helper/podspec.rb +1 -0
  12. data/lib/cocoapods-binary-cache/hooks/post_install.rb +18 -1
  13. data/lib/cocoapods-binary-cache/hooks/pre_install.rb +7 -10
  14. data/lib/cocoapods-binary-cache/main.rb +2 -1
  15. data/lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/target_definition.rb +1 -1
  16. data/lib/cocoapods-binary-cache/pod-binary/helper/feature_switches.rb +0 -38
  17. data/lib/cocoapods-binary-cache/pod-binary/helper/names.rb +2 -11
  18. data/lib/cocoapods-binary-cache/pod-binary/helper/prebuild_sandbox.rb +1 -2
  19. data/lib/cocoapods-binary-cache/pod-binary/integration.rb +0 -1
  20. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/source_installation.rb +2 -0
  21. data/lib/cocoapods-binary-cache/pod-binary/integration/remove_target_files.rb +2 -2
  22. data/lib/cocoapods-binary-cache/pod-binary/integration/source_installer.rb +1 -0
  23. data/lib/cocoapods-binary-cache/pod-binary/prebuild.rb +23 -13
  24. data/lib/cocoapods-binary-cache/pod-binary/prebuild_dsl.rb +3 -0
  25. data/lib/cocoapods-binary-cache/pod-rome/build_framework.rb +26 -25
  26. data/lib/cocoapods-binary-cache/prebuild_output/metadata.rb +16 -0
  27. data/lib/cocoapods-binary-cache/prebuild_output/output.rb +8 -37
  28. data/lib/command/binary.rb +2 -2
  29. data/lib/command/config.rb +7 -7
  30. data/lib/command/executor/fetcher.rb +1 -1
  31. data/lib/command/executor/prebuilder.rb +1 -1
  32. data/lib/command/executor/pusher.rb +1 -1
  33. data/lib/command/push.rb +23 -0
  34. metadata +8 -4
  35. data/lib/cocoapods-binary-cache/prebuild_cache.rb +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7da9e54a448a2db99d8e9870096b80872868f2593d365298907a499676383e78
4
- data.tar.gz: 6317b96160456163abb6cebf49b92f066b405ae312d9918d864cff8449b0c3f2
3
+ metadata.gz: 7896d5bccb5c1b995271da31a02a9374ff4abc833e081bff2b38fe2401dfa2da
4
+ data.tar.gz: ca520b237ddf0377a1e1ca03f90e5f4afa79f576241662ae22c3a9fc86e158c5
5
5
  SHA512:
6
- metadata.gz: cd63f945a80479d7c25bb52fc57f0659aba555da7e7f27308ad406d12806418cab69ab7ca6f3575dfdd2902bf69cb19127aa39e422dc8af1b1ed291c1d2497a0
7
- data.tar.gz: f7b9d360fe8d2f81f784c3c8c0dd1481c904c0462b87af0fa968a981609f85de8213e0074ca3691e871627bfc19530400e1012740250068f1cb3550e3018cf2a
6
+ metadata.gz: 3a7a9a3decaa6a14b80c80b77e69576a9b77ccbb3b4a5760c23c6e02b7ebc809a1e326ccf19030d6a1e091cdaa21a2a0d14c141d87457e7fdba7742c04adcf37
7
+ data.tar.gz: 4b6c9a841f4b98d41b1ad1ed36aaab65e7c7b59cd4ee30b1b13b0f695b264a0ef1222007adf305cab0be216d175f41d471a61368f641653592a31b5e23ecff1f
@@ -1,7 +1,6 @@
1
1
  module PodPrebuild
2
- class CacheValidator < BaseCacheValidator
2
+ class CacheValidator
3
3
  def initialize(options)
4
- super(options)
5
4
  @validators = [
6
5
  PodPrebuild::PodfileChangesCacheValidator.new(options),
7
6
  PodPrebuild::NonDevPodsCacheValidator.new(options)
@@ -37,6 +37,7 @@ module PodPrebuild
37
37
  hit = Set.new
38
38
 
39
39
  check_pod = lambda do |name|
40
+ root_name = name.split("/")[0]
40
41
  version = pods[name]
41
42
  prebuilt_version = prebuilt_pods[name]
42
43
  result = false
@@ -44,13 +45,15 @@ module PodPrebuild
44
45
  missed[name] = "Not available (#{version})"
45
46
  elsif prebuilt_version != version
46
47
  missed[name] = "Outdated: (prebuilt: #{prebuilt_version}) vs (#{version})"
48
+ elsif load_metadata(root_name).blank?
49
+ missed[name] = "Metadata not available (probably #{root_name}.zip is not in GeneratedFrameworks)"
47
50
  else
48
- settings_diff = incompatible_build_settings(name)
49
- if settings_diff.empty?
51
+ diff = incompatible_pod(root_name)
52
+ if diff.empty?
50
53
  hit << name
51
54
  result = true
52
55
  else
53
- missed[name] = "Incompatible build settings: #{settings_diff}"
56
+ missed[name] = "Incompatible: #{diff}"
54
57
  end
55
58
  end
56
59
  result
@@ -70,11 +73,10 @@ module PodPrebuild
70
73
  PodPrebuild::CacheValidationResult.new(missed, hit)
71
74
  end
72
75
 
73
- def read_prebuilt_build_settings(name)
74
- return {} if generated_framework_path.nil?
75
-
76
- metadata = PodPrebuild::Metadata.in_dir(generated_framework_path + name)
77
- metadata.build_settings
76
+ def incompatible_pod(name)
77
+ # Pod incompatibility is a universal concept. Generally, it requires build settings compatibility.
78
+ # For more checks, do override this function to define what it means by `incompatible`.
79
+ incompatible_build_settings(name)
78
80
  end
79
81
 
80
82
  def incompatible_build_settings(name)
@@ -88,5 +90,23 @@ module PodPrebuild
88
90
  end
89
91
  settings_diff
90
92
  end
93
+
94
+ def load_metadata(name)
95
+ @metadata_cache ||= {}
96
+ cache = @metadata_cache[name]
97
+ return cache unless cache.nil?
98
+
99
+ metadata = PodPrebuild::Metadata.in_dir(generated_framework_path + name)
100
+ @metadata_cache[name] = metadata
101
+ metadata
102
+ end
103
+
104
+ def read_prebuilt_build_settings(name)
105
+ load_metadata(name).build_settings
106
+ end
107
+
108
+ def read_source_hash(name)
109
+ load_metadata(name).source_hash
110
+ end
91
111
  end
92
112
  end
@@ -1,22 +1,30 @@
1
1
  module PodPrebuild
2
2
  class DevPodsCacheValidator < BaseCacheValidator
3
- def initialize(options)
4
- super(options)
5
- @sandbox_root = options[:sandbox_root]
6
- end
7
-
8
3
  def validate(*)
9
4
  return PodPrebuild::CacheValidationResult.new if @pod_lockfile.nil?
10
5
 
11
- # TODO (thuyen): Logic needs to be revised
12
- # TODO (thuyen): Migrate the code PodCacheValidator.verify_devpod_checksum to this place
13
- missed_with_checksum, hit_with_checksum = PodCacheValidator.verify_devpod_checksum(
14
- @sandbox_root,
15
- @generated_framework_path,
16
- @pod_lockfile.lockfile
6
+ validate_pods(
7
+ pods: @pod_lockfile.dev_pods,
8
+ subspec_pods: [],
9
+ prebuilt_pods: @prebuilt_lockfile.nil? ? {} : @prebuilt_lockfile.dev_pods
17
10
  )
18
- missed = missed_with_checksum.transform_values { |checksum| "Checksum changed: #{checksum}" }
19
- PodPrebuild::CacheValidationResult.new(missed, hit_with_checksum.keys.to_set)
11
+ end
12
+
13
+ def incompatible_pod(name)
14
+ diff = super(name)
15
+ return diff unless diff.empty?
16
+
17
+ incompatible_source(name)
18
+ end
19
+
20
+ def incompatible_source(name)
21
+ diff = {}
22
+ prebuilt_hash = read_source_hash(name)
23
+ expected_hash = pod_lockfile.dev_pod_hash(name)
24
+ unless prebuilt_hash == expected_hash
25
+ diff[name] = { :prebuilt_hash => prebuilt_hash, :expected_hash => expected_hash}
26
+ end
27
+ diff
20
28
  end
21
29
  end
22
30
  end
@@ -5,7 +5,7 @@ module PodPrebuild
5
5
 
6
6
  validate_pods(
7
7
  pods: @pod_lockfile.non_dev_pods,
8
- subspec_pods: @pod_lockfile.subspec_pods,
8
+ subspec_pods: @pod_lockfile.subspec_vendor_pods,
9
9
  prebuilt_pods: @prebuilt_lockfile.nil? ? {} : @prebuilt_lockfile.non_dev_pods
10
10
  )
11
11
  end
@@ -0,0 +1,13 @@
1
+ module PodPrebuild
2
+ class BaseDiagnosis
3
+ def initialize(options)
4
+ @cache_validation = options[:cache_validation]
5
+ @standard_sandbox = options[:standard_sandbox]
6
+ @specs = (options[:specs] || []).map { |s| [s.name, s] }.to_h
7
+ end
8
+
9
+ def spec(name)
10
+ @specs[name]
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ require_relative "base"
2
+ require_relative "integration"
3
+
4
+ module PodPrebuild
5
+ class Diagnosis
6
+ def initialize(options)
7
+ @diagnosers = [
8
+ IntegrationDiagnosis
9
+ ].map { |klazz| klazz.new(options) }
10
+ end
11
+
12
+ def run
13
+ @diagnosers.each(&:run)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "base"
2
+
3
+ module PodPrebuild
4
+ class IntegrationDiagnosis < BaseDiagnosis
5
+ def run
6
+ should_be_integrated = if Pod::Podfile::DSL.prebuild_job? \
7
+ then @cache_validation.hit + @cache_validation.missed \
8
+ else @cache_validation.hit \
9
+ end
10
+ should_be_integrated = should_be_integrated.map { |name| name.split("/")[0] }.to_set
11
+ unintegrated = should_be_integrated.reject do |name|
12
+ module_name = spec(name)&.module_name || name
13
+ framework_path = @standard_sandbox.pod_dir(name) + "#{module_name}.framework"
14
+ framework_path.exist?
15
+ end
16
+ Pod::UI.puts "🚩 Unintegrated frameworks: #{unintegrated}".yellow unless unintegrated.empty?
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ module PodPrebuild
2
+ class Env
3
+ @stage_idx = 0
4
+
5
+ class << self
6
+ def reset!
7
+ @stage_idx = 0
8
+ @stages = nil
9
+ end
10
+
11
+ def next_stage!
12
+ @stage_idx += 1 if @stage_idx < stages.count - 1
13
+ end
14
+
15
+ def stages
16
+ @stages ||= Pod::Podfile::DSL.prebuild_job? ? [:prebuild, :integration] : [:integration]
17
+ end
18
+
19
+ def current_stage
20
+ stages[@stage_idx]
21
+ end
22
+
23
+ def prebuild_stage?
24
+ current_stage == :prebuild
25
+ end
26
+
27
+ def integration_stage?
28
+ current_stage == :integration
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,3 +1,5 @@
1
+ require_relative "checksum"
2
+
1
3
  module PodPrebuild
2
4
  class Lockfile
3
5
  attr_reader :lockfile, :data
@@ -15,6 +17,10 @@ module PodPrebuild
15
17
  @data["EXTERNAL SOURCES"] || {}
16
18
  end
17
19
 
20
+ def dev_pod_sources
21
+ @dev_pod_sources ||= external_sources.select { |_, attributes| attributes.key?(:path) } || {}
22
+ end
23
+
18
24
  def dev_pod_names
19
25
  # There are 2 types of external sources:
20
26
  # - Development pods: declared with `:path` option in Podfile, corresponding to `:path` in the Lockfile
@@ -27,7 +33,7 @@ module PodPrebuild
27
33
  # :git: git@remote_url
28
34
  # :commit: abc1234
29
35
  # --------------------
30
- @dev_pod_names ||= external_sources.select { |_, attributes| attributes.key?(:path) }.keys.to_set
36
+ @dev_pod_names ||= dev_pod_sources.keys.to_set
31
37
  end
32
38
 
33
39
  def dev_pods
@@ -40,13 +46,30 @@ module PodPrebuild
40
46
  @non_dev_pods ||= pods.reject { |name, _| dev_pod_names_.include?(name) }
41
47
  end
42
48
 
49
+ def subspec_vendor_pods
50
+ dev_pod_names_ = dev_pod_names
51
+ @subspec_vendor_pods ||= subspec_pods.reject { |name, _| dev_pod_names_.include?(name) }
52
+ end
53
+
54
+ # Return content hash (Hash the directory at source path) of a dev_pod
55
+ # Return nil if it's not a dev_pod
56
+ def dev_pod_hash(pod_name)
57
+ dev_pod_hashes_map[pod_name]
58
+ end
59
+
60
+ private
61
+
43
62
  def subspec_pods
44
- pods.keys
63
+ @subspec_pods ||= pods.keys
45
64
  .select { |k| k.include?("/") }
46
65
  .group_by { |k| k.split("/")[0] }
47
66
  end
48
67
 
49
- private
68
+ # Generate a map between a dev_pod and it source hash
69
+ def dev_pod_hashes_map
70
+ @dev_pod_hashes_map ||=
71
+ dev_pod_sources.map { |name, attribs| [name, FolderChecksum.checksum(attribs[:path])] }.to_h
72
+ end
50
73
 
51
74
  # Parse an item under `PODS` section of a Lockfile
52
75
  # @param hash_or_string: an item under `PODS` section, could be a Hash (if having dependencies) or a String
@@ -1,5 +1,6 @@
1
1
  module Pod
2
2
  class Specification
3
+ # TODO: this detect objc lib as empty source, eg. Realm
3
4
  def empty_source_files?
4
5
  return subspecs.all?(&:empty_source_files?) unless subspecs.empty?
5
6
 
@@ -5,12 +5,29 @@ module PodPrebuild
5
5
  end
6
6
 
7
7
  def run
8
+ edit_scheme_for_code_coverage if PodPrebuild::Env.prebuild_stage?
9
+ diagnose if PodPrebuild::Env.integration_stage?
10
+ end
11
+
12
+ private
13
+
14
+ def diagnose
15
+ Pod::UI.section("Diagnosing cocoapods-binary-cache") do
16
+ PodPrebuild::Diagnosis.new(
17
+ cache_validation: PodPrebuild::StateStore.cache_validation,
18
+ standard_sandbox: @installer_context.sandbox,
19
+ specs: @installer_context.umbrella_targets.map(&:specs).flatten
20
+ ).run
21
+ end
22
+ end
23
+
24
+ def edit_scheme_for_code_coverage
8
25
  return unless Pod::Podfile::DSL.dev_pods_enabled && @installer_context.sandbox.instance_of?(Pod::PrebuildSandbox)
9
26
 
10
27
  # Modify pods scheme to support code coverage
11
28
  # If we don't prebuild dev pod -> no need to care about this in Pod project
12
29
  # because we setup in the main project (ex. DriverCI scheme)
13
- SchemeEditor.edit_to_support_code_coverage(@installer_context.sandbox) if Pod.is_prebuild_stage
30
+ SchemeEditor.edit_to_support_code_coverage(@installer_context.sandbox)
14
31
  end
15
32
  end
16
33
  end
@@ -13,18 +13,21 @@ module PodPrebuild
13
13
  end
14
14
 
15
15
  def run
16
+ return if @installer_context.sandbox.is_a?(Pod::PrebuildSandbox)
17
+
16
18
  require_relative "../pod-binary/helper/feature_switches"
17
- return if Pod.is_prebuild_stage
18
19
 
19
20
  log_section "🚀 Prebuild frameworks"
20
21
  ensure_valid_podfile
21
22
  save_installation_states
22
- prepare_environment
23
+ Pod::UI.section("Prepare environment") { prepare_environment }
23
24
  create_prebuild_sandbox
24
25
  Pod::UI.section("Detect implicit dependencies") { detect_implicit_dependencies }
25
26
  Pod::UI.section("Validate prebuilt cache") { validate_cache }
26
27
  prebuild! if Pod::Podfile::DSL.prebuild_job?
27
- reset_environment
28
+ Pod::UI.section("Reset environment") { reset_environment }
29
+
30
+ PodPrebuild::Env.next_stage!
28
31
  log_section "🤖 Resume pod installation"
29
32
  require_relative "../pod-binary/integration"
30
33
  end
@@ -53,19 +56,13 @@ module PodPrebuild
53
56
  end
54
57
 
55
58
  def prepare_environment
56
- Pod::UI.puts "Prepare environment"
57
- Pod.is_prebuild_stage = true
58
- Pod::Podfile::DSL.enable_prebuild_patch true # enable sikpping for prebuild targets
59
59
  Pod::Installer.force_disable_integration true # don't integrate targets
60
60
  Pod::Config.force_disable_write_lockfile true # disbale write lock file for perbuild podfile
61
61
  Pod::Installer.disable_install_complete_message true # disable install complete message
62
62
  end
63
63
 
64
64
  def reset_environment
65
- Pod::UI.puts "Reset environment"
66
- Pod.is_prebuild_stage = false
67
65
  Pod::Installer.force_disable_integration false
68
- Pod::Podfile::DSL.enable_prebuild_patch false
69
66
  Pod::Config.force_disable_write_lockfile false
70
67
  Pod::Installer.disable_install_complete_message false
71
68
  Pod::UserInterface.warnings = [] # clean the warning in the prebuild step, it's duplicated.
@@ -81,7 +78,7 @@ module PodPrebuild
81
78
  def create_prebuild_sandbox
82
79
  standard_sandbox = installer_context.sandbox
83
80
  @prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sandbox)
84
- Pod::UI.puts "Create prebuild sandbox at #{@prebuild_sandbox.root}"
81
+ Pod::UI.message "Create prebuild sandbox at #{@prebuild_sandbox.root}"
85
82
  end
86
83
 
87
84
  def detect_implicit_dependencies
@@ -9,13 +9,14 @@ require_relative "helper/json"
9
9
  require_relative "helper/lockfile"
10
10
  require_relative "helper/path_utils"
11
11
  require_relative "helper/podspec"
12
+ require_relative "env"
12
13
  require_relative "state_store"
13
14
  require_relative "hooks/post_install"
14
15
  require_relative "hooks/pre_install"
15
16
  require_relative "pod-binary/prebuild_dsl"
16
17
  require_relative "pod-binary/prebuild_hook"
17
18
  require_relative "pod-binary/prebuild"
18
- require_relative "prebuild_cache"
19
19
  require_relative "prebuild_output/metadata"
20
20
  require_relative "prebuild_output/output"
21
21
  require_relative "scheme_editor"
22
+ require_relative "diagnosis/diagnosis"
@@ -3,7 +3,7 @@ module Pod
3
3
  class TargetDefinition
4
4
  def detect_prebuilt_pod(name, requirements)
5
5
  @explicit_prebuilt_pod_names ||= []
6
- options = requirements.last
6
+ options = requirements.last || {}
7
7
  if Pod::Podfile::DSL.prebuild_all?
8
8
  @explicit_prebuilt_pod_names << Specification.root_name(name)
9
9
  elsif options.is_a?(Hash) && options[:binary]
@@ -2,44 +2,6 @@ require_relative "../tool/tool"
2
2
  require_relative "prebuild_sandbox"
3
3
 
4
4
  module Pod
5
-
6
- # a flag that indicate stages
7
- class_attr_accessor :is_prebuild_stage
8
-
9
- # a switch for the `pod` DSL to make it only valid for ':binary => true'
10
- class Podfile
11
- module DSL
12
- @@enable_prebuild_patch = false
13
-
14
- # when enable, `pod` function will skip all pods without 'prebuild => true'
15
- def self.enable_prebuild_patch(value)
16
- @@enable_prebuild_patch = value
17
- end
18
-
19
- # --- patch ---
20
- old_method = instance_method(:pod)
21
-
22
- define_method(:pod) do |name, *args|
23
- if !@@enable_prebuild_patch
24
- old_method.bind(self).(name, *args)
25
- return
26
- end
27
-
28
- # patched content
29
- should_prebuild = Pod::Podfile::DSL.prebuild_all
30
- local = false
31
-
32
- options = args.last
33
- if options.is_a?(Hash) and options[Pod::Prebuild.keyword] != nil
34
- should_prebuild = options[Pod::Prebuild.keyword]
35
- local = (options[:path] != nil)
36
- end
37
-
38
- old_method.bind(self).call(name, *args) if should_prebuild && (!local || Podfile::DSL.dev_pods_enabled)
39
- end
40
- end
41
- end
42
-
43
5
  # a force disable option for integral
44
6
  class Installer
45
7
  def self.force_disable_integration(value)
@@ -18,19 +18,10 @@
18
18
  module Pod
19
19
  def self.fast_get_targets_for_pod_name(pod_name, targets, cache)
20
20
  pod_name = pod_name.split("/")[0] # Look for parent spec instead of subspecs
21
- pod_name_to_targets_hash = nil
22
21
  if cache.empty?
23
- pod_name_to_targets_hash = targets.reduce({}) do |sum, target|
24
- array = sum[target.pod_name] || []
25
- array << target
26
- sum[target.pod_name] = array
27
- sum
28
- end
29
- cache << pod_name_to_targets_hash
22
+ targets.select { |target| target.name == pod_name }
30
23
  else
31
- pod_name_to_targets_hash = cache.first
24
+ cache.first[pod_name] || []
32
25
  end
33
-
34
- pod_name_to_targets_hash[pod_name] || []
35
26
  end
36
27
  end
@@ -2,10 +2,9 @@ require_relative "names"
2
2
 
3
3
  module Pod
4
4
  class PrebuildSandbox < Sandbox
5
-
6
5
  # [String] standard_sandbox_path
7
6
  def self.from_standard_sanbox_path(path)
8
- prebuild_sandbox_path = Pathname.new(path).realpath + "_Prebuild"
7
+ prebuild_sandbox_path = Pathname.new(path).realpath + ".." + PodPrebuild::Config.instance.prebuild_path
9
8
  self.new(prebuild_sandbox_path)
10
9
  end
11
10
 
@@ -5,7 +5,6 @@ require_relative "helper/names"
5
5
  require_relative "helper/target_checker"
6
6
  require_relative "integration/alter_specs"
7
7
  require_relative "integration/remove_target_files"
8
- require_relative "integration/source_installer"
9
8
  require_relative "integration/validation"
10
9
  require_relative "integration/patch/embed_framework_script"
11
10
  require_relative "integration/patch/resolve_dependencies"
@@ -1,3 +1,5 @@
1
+ require_relative "../source_installer"
2
+
1
3
  module Pod
2
4
  class Installer
3
5
  # Override the download step to skip download and prepare file in target folder
@@ -15,9 +15,9 @@ module Pod
15
15
 
16
16
  updated_names.each do |name|
17
17
  root_name = Specification.root_name(name)
18
- next if !Pod::Podfile::DSL.dev_pods_enabled && sandbox.local?(root_name)
18
+ next if sandbox.local?(root_name)
19
19
 
20
- UI.puts "Delete cached files: #{root_name}"
20
+ UI.message "Delete cached files: #{root_name}"
21
21
  target_path = sandbox.pod_dir(root_name)
22
22
  target_path.rmtree if target_path.exist?
23
23
 
@@ -14,6 +14,7 @@ module Pod
14
14
  return if !Podfile::DSL.dev_pods_enabled && standard_sanbox.local?(name)
15
15
 
16
16
  # make a symlink to target folder
17
+ # TODO (bang): Unify to 1 sandbox to optimize and avoid inconsistency
17
18
  prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sanbox)
18
19
  # if spec used in multiple platforms, it may return multiple paths
19
20
  target_names = prebuild_sandbox.existed_target_names_for_pod_name(self.name)
@@ -3,6 +3,7 @@ require_relative "../pod-rome/build_framework"
3
3
  require_relative "../prebuild_output/output"
4
4
  require_relative "helper/passer"
5
5
  require_relative "helper/target_checker"
6
+ require_relative "../helper/lockfile"
6
7
 
7
8
  # patch prebuild ability
8
9
  module Pod
@@ -10,6 +11,7 @@ module Pod
10
11
  def initialize(options)
11
12
  super(options[:sandbox], options[:podfile], options[:lockfile])
12
13
  @cache_validation = options[:cache_validation]
14
+ @lockfile_wrapper = PodPrebuild::Lockfile.new(lockfile)
13
15
  end
14
16
 
15
17
  private
@@ -35,15 +37,13 @@ module Pod
35
37
  PodPrebuild::StateStore.excluded_pods.include?(name)
36
38
  end
37
39
 
38
- def cache_hit?(name)
39
- @cache_validation.hit?(name)
40
+ def cache_missed?(name)
41
+ @cache_validation.missed?(name)
40
42
  end
41
43
 
42
44
  def should_not_prebuild_vendor_pod(name)
43
45
  return true if blacklisted?(name)
44
46
  return false if Pod::Podfile::DSL.prebuild_all_vendor_pods
45
-
46
- cache_hit?(name)
47
47
  end
48
48
 
49
49
  public
@@ -98,6 +98,9 @@ module Pod
98
98
  targets = pod_targets
99
99
  end
100
100
 
101
+ unless Pod::Podfile::DSL.prebuild_all_vendor_pods
102
+ targets = targets.select { |pod_target| cache_missed?(pod_target.name) }
103
+ end
101
104
  targets = targets.reject { |pod_target| should_not_prebuild_vendor_pod(pod_target.name) }
102
105
  targets = targets.reject { |pod_target| sandbox.local?(pod_target.pod_name) } unless Podfile::DSL.dev_pods_enabled
103
106
 
@@ -115,13 +118,14 @@ module Pod
115
118
  output_path = sandbox.framework_folder_path_for_target_name(target.name)
116
119
  output_path.mkpath unless output_path.exist?
117
120
  Pod::Prebuild.build(
118
- sandbox_path,
119
- target,
120
- Pod::Podfile::DSL.prebuild_config,
121
- output_path,
122
- bitcode_enabled,
123
- Pod::Podfile::DSL.custom_device_build_options,
124
- Pod::Podfile::DSL.custom_simulator_build_options
121
+ sandbox_root_path: sandbox_path,
122
+ target: target,
123
+ configuration: Pod::Podfile::DSL.prebuild_config,
124
+ output_path: output_path,
125
+ bitcode_enabled: bitcode_enabled,
126
+ device_build_enabled: Pod::Podfile::DSL.device_build_enabled,
127
+ custom_build_options: Pod::Podfile::DSL.custom_device_build_options,
128
+ custom_build_options_simulator: Pod::Podfile::DSL.custom_simulator_build_options
125
129
  )
126
130
  collect_metadata(target, output_path)
127
131
  end
@@ -188,7 +192,6 @@ module Pod
188
192
  Pod::UI.puts "Targets to cleanup: #{deleted_target_names}"
189
193
 
190
194
  prebuild_output.write_delta_file(updated_target_names, deleted_target_names)
191
- prebuild_output.process_prebuilt_dev_pods
192
195
  end
193
196
 
194
197
  def clean_delta_file
@@ -211,6 +214,13 @@ module Pod
211
214
  .build_configurations
212
215
  .detect { |config| config.name == Pod::Podfile::DSL.prebuild_config }
213
216
  .build_settings
217
+ hash = @lockfile_wrapper.dev_pod_hash(target.name)
218
+ metadata.source_hash = hash unless hash.nil?
219
+
220
+ # Store root path for code-coverage support later
221
+ # TODO: update driver code-coverage logic to use path stored here
222
+ project_root = PathUtils.remove_last_path_component(@sandbox.standard_sanbox_path.to_s)
223
+ metadata.project_root = project_root
214
224
  metadata.save!
215
225
  end
216
226
 
@@ -218,7 +228,7 @@ module Pod
218
228
  old_method2 = instance_method(:run_plugins_post_install_hooks)
219
229
  define_method(:run_plugins_post_install_hooks) do
220
230
  old_method2.bind(self).call
221
- prebuild_frameworks! if Pod.is_prebuild_stage && Pod::Podfile::DSL.prebuild_job?
231
+ prebuild_frameworks! if PodPrebuild::Env.prebuild_stage?
222
232
  end
223
233
  end
224
234
  end
@@ -14,6 +14,7 @@ module Pod
14
14
  apply_config.call(:excluded_pods)
15
15
  apply_config.call(:dev_pods_enabled)
16
16
  apply_config.call(:bitcode_enabled)
17
+ apply_config.call(:device_build_enabled)
17
18
  apply_config.call(:dont_remove_source_code)
18
19
  apply_config.call(:custom_device_build_options)
19
20
  apply_config.call(:custom_simulator_build_options)
@@ -28,6 +29,7 @@ module Pod
28
29
  @excluded_pods = Set.new
29
30
  @dev_pods_enabled = false
30
31
  @bitcode_enabled = false
32
+ @device_build_enabled = false
31
33
  @dont_remove_source_code = false
32
34
  @custom_device_build_options = []
33
35
  @custom_simulator_build_options = []
@@ -52,6 +54,7 @@ module Pod
52
54
  attr_accessor :excluded_pods
53
55
  attr_accessor :dev_pods_enabled
54
56
  attr_accessor :bitcode_enabled
57
+ attr_accessor :device_build_enabled
55
58
  attr_accessor :dont_remove_source_code
56
59
  attr_accessor :custom_device_build_options
57
60
  attr_accessor :custom_simulator_build_options
@@ -1,6 +1,13 @@
1
1
  require 'fourflusher'
2
2
  require 'xcpretty' # TODO (thuyen): Revise this dependency
3
3
 
4
+ module FileUtils
5
+ def self.mvpath(src, dst, **options)
6
+ FileUtils.rm_rf(File.join(dst, File.basename(src)))
7
+ FileUtils.mv(src, dst, **options)
8
+ end
9
+ end
10
+
4
11
  PLATFORMS = { 'iphonesimulator' => 'iOS',
5
12
  'appletvsimulator' => 'tvOS',
6
13
  'watchsimulator' => 'watchOS' }
@@ -76,14 +83,14 @@ def build_for_iosish_platform(sandbox,
76
83
  device_binary = device_framework_path + "/#{module_name}"
77
84
  simulator_binary = simulator_framework_path + "/#{module_name}"
78
85
  return unless File.file?(device_binary) && File.file?(simulator_binary)
79
-
86
+
80
87
  # the device_lib path is the final output file path
81
88
  # combine the binaries
82
89
  tmp_lipoed_binary_path = "#{build_dir}/#{target_name}"
83
90
  lipo_log = `lipo -create -output #{tmp_lipoed_binary_path} #{device_binary} #{simulator_binary}`
84
91
  puts lipo_log unless File.exist?(tmp_lipoed_binary_path)
85
- FileUtils.mv tmp_lipoed_binary_path, device_binary, :force => true
86
-
92
+ FileUtils.mvpath tmp_lipoed_binary_path, device_binary
93
+
87
94
  # collect the swiftmodule file for various archs.
88
95
  device_swiftmodule_path = device_framework_path + "/Modules/#{module_name}.swiftmodule"
89
96
  simulator_swiftmodule_path = simulator_framework_path + "/Modules/#{module_name}.swiftmodule"
@@ -123,16 +130,14 @@ def build_for_iosish_platform(sandbox,
123
130
  tmp_lipoed_binary_path = "#{output_path}/#{module_name}.draft"
124
131
  lipo_log = `lipo -create -output #{tmp_lipoed_binary_path} #{device_dsym}/Contents/Resources/DWARF/#{module_name} #{simulator_dsym}/Contents/Resources/DWARF/#{module_name}`
125
132
  puts lipo_log unless File.exist?(tmp_lipoed_binary_path)
126
- FileUtils.mv tmp_lipoed_binary_path, "#{device_framework_path}.dSYM/Contents/Resources/DWARF/#{module_name}", :force => true
133
+ FileUtils.mvpath tmp_lipoed_binary_path, "#{device_framework_path}.dSYM/Contents/Resources/DWARF/#{module_name}"
127
134
  end
128
- # move
129
- FileUtils.mv device_dsym, output_path, :force => true
135
+ FileUtils.mvpath device_dsym, output_path
130
136
  end
131
137
 
132
138
  # output
133
139
  output_path.mkpath unless output_path.exist?
134
- FileUtils.mv device_framework_path, output_path, :force => true
135
-
140
+ FileUtils.mvpath device_framework_path, output_path
136
141
  end
137
142
 
138
143
  def xcodebuild(sandbox, target, configuration, sdk='macosx', deployment_target=nil, other_options=[])
@@ -168,23 +173,18 @@ def xcodebuild(sandbox, target, configuration, sdk='macosx', deployment_target=n
168
173
  [is_succeed, log]
169
174
  end
170
175
 
171
-
172
-
173
176
  module Pod
174
177
  class Prebuild
178
+ def self.build(options)
179
+ sandbox_root_path = options[:sandbox_root_path]
180
+ target = options[:target]
181
+ configuration = options[:configuration]
182
+ output_path = options[:output_path]
183
+ bitcode_enabled = options[:bitcode_enabled] || false
184
+ device_build_enabled = options[:device_build_enabled] || false
185
+ custom_build_options = options[:custom_build_options] || []
186
+ custom_build_options_simulator = options[:custom_build_options_simulator] || []
175
187
 
176
- # Build the frameworks with sandbox and targets
177
- #
178
- # @param [String] sandbox_root_path
179
- # The sandbox root path where the targets project place
180
- #
181
- # [PodTarget] target
182
- # The pod targets to build
183
- #
184
- # [Pathname] output_path
185
- # output path for generated frameworks
186
- #
187
- def self.build(sandbox_root_path, target, configuration, output_path, bitcode_enabled = false, custom_build_options=[], custom_build_options_simulator=[])
188
188
  return if target.nil?
189
189
 
190
190
  sandbox_root = Pathname(sandbox_root_path)
@@ -204,7 +204,8 @@ module Pod
204
204
  "iphonesimulator",
205
205
  bitcode_enabled,
206
206
  custom_build_options,
207
- custom_build_options_simulator
207
+ custom_build_options_simulator,
208
+ device_build_enabled
208
209
  )
209
210
  when :osx
210
211
  xcodebuild(
@@ -227,7 +228,8 @@ module Pod
227
228
  "watchsimulator",
228
229
  true,
229
230
  custom_build_options,
230
- custom_build_options_simulator
231
+ custom_build_options_simulator,
232
+ device_build_enabled
231
233
  )
232
234
  else raise "Unsupported platform for '#{target.name}': '#{target.platform.name}'" end
233
235
 
@@ -242,6 +244,5 @@ module Pod
242
244
  def self.build_dir(sandbox_root)
243
245
  sandbox_root.parent + "build"
244
246
  end
245
-
246
247
  end
247
248
  end
@@ -43,5 +43,21 @@ module PodPrebuild
43
43
  def build_settings=(value)
44
44
  @data["build_settings"] = value
45
45
  end
46
+
47
+ def source_hash
48
+ @data["source_hash"] || {}
49
+ end
50
+
51
+ def source_hash=(value)
52
+ @data["source_hash"] = value
53
+ end
54
+
55
+ def project_root
56
+ @data["project_root"]
57
+ end
58
+
59
+ def project_root=(value)
60
+ @data["project_root"] = value
61
+ end
46
62
  end
47
63
  end
@@ -7,18 +7,17 @@ module PodPrebuild
7
7
  @sandbox = prebuild_sandbox
8
8
  end
9
9
 
10
- def delta_dir
11
- @delta_dir ||= File.expand_path("#{@sandbox.root}/../_Prebuild_delta")
10
+ def prebuild_delta_path
11
+ @prebuild_delta_path ||= PodPrebuild::Config.instance.prebuild_delta_path
12
12
  end
13
13
 
14
- def delta_file_path
15
- # TODO (thuyen): Unify this path with PodPrebuild::Config#delta_file_path
16
- "#{delta_dir}/changes.json"
14
+ def delta_dir
15
+ @delta_dir ||= File.dirname(prebuild_delta_path)
17
16
  end
18
17
 
19
18
  def clean_delta_file
20
- puts "Clean delta file: #{delta_file_path}"
21
- FileUtils.rm_rf(delta_file_path)
19
+ puts "Clean delta file: #{prebuild_delta_path}"
20
+ FileUtils.rm_rf(prebuild_delta_path)
22
21
  end
23
22
 
24
23
  def create_dir_if_needed(dir)
@@ -32,40 +31,12 @@ module PodPrebuild
32
31
  return
33
32
  end
34
33
 
35
- Pod::UI.puts "Write prebuild changes to: #{delta_file_path}"
34
+ Pod::UI.puts "Write prebuild changes to: #{prebuild_delta_path}"
36
35
  create_dir_if_needed(delta_dir)
37
- changes = PodPrebuild::JSONFile.new(delta_file_path)
36
+ changes = PodPrebuild::JSONFile.new(prebuild_delta_path)
38
37
  changes["updated"] = updated
39
38
  changes["deleted"] = deleted
40
39
  changes.save!
41
40
  end
42
-
43
- def process_prebuilt_dev_pods
44
- devpod_output_path = "#{delta_dir}/devpod_prebuild_output/"
45
- create_dir_if_needed(devpod_output_path)
46
- Pod::UI.puts "Copy prebuilt devpod frameworks to output dir: #{devpod_output_path}"
47
-
48
- # Inject project path (where the framework is built) to support generating code coverage later
49
- project_root = PathUtils.remove_last_path_component(@sandbox.standard_sanbox_path.to_s)
50
- template_file_path = devpod_output_path + "prebuilt_map"
51
- File.open(template_file_path, "w") do |file|
52
- file.write(project_root)
53
- end
54
-
55
- # FIXME (thuyen): Revise usage of cache_miss_dev_pods_dic
56
- # The behavior of processing outputs of dev pods and non-dev pods should be very SIMILAR
57
- cache_miss_dev_pods_dic = {}
58
-
59
- cache_miss_dev_pods_dic.each do |name, hash|
60
- Pod::UI.puts "Output dev pod lib: #{name} hash: #{hash}"
61
- built_lib_path = @sandbox.framework_folder_path_for_target_name(name)
62
- next unless File.directory?(built_lib_path)
63
-
64
- FileUtils.cp(template_file_path, "#{built_lib_path}/#{name}.framework")
65
- target_dir = "#{devpod_output_path}#{name}_#{hash}"
66
- Pod::UI.puts "From: #{built_lib_path} -> #{target_dir}"
67
- FileUtils.cp_r(built_lib_path, target_dir)
68
- end
69
- end
70
41
  end
71
42
  end
@@ -2,16 +2,16 @@ require "fileutils"
2
2
  require_relative "config"
3
3
  require_relative "fetch"
4
4
  require_relative "prebuild"
5
+ require_relative "push"
5
6
  require_relative "visualize"
6
7
 
7
8
  module Pod
8
9
  class Command
9
10
  class Binary < Command
10
11
  self.abstract_command = true
11
- self.default_subcommand = "fetch"
12
12
 
13
13
  def prebuild_config
14
- @prebuild_config ||= PodPrebuild::Config.new("PodBinaryCacheConfig.json")
14
+ @prebuild_config ||= PodPrebuild::Config.instance
15
15
  end
16
16
  end
17
17
  end
@@ -2,13 +2,18 @@ require_relative "../cocoapods-binary-cache/helper/json"
2
2
 
3
3
  module PodPrebuild
4
4
  class Config
5
- attr_reader :cache_repo, :cache_path, :prebuild_path
5
+ attr_reader :cache_repo, :cache_path, :prebuild_path, :prebuild_delta_path
6
6
 
7
7
  def initialize(path)
8
8
  @data = PodPrebuild::JSONFile.new(path)
9
9
  @cache_repo = @data["cache_repo"] || @data["prebuilt_cache_repo"]
10
10
  @cache_path = File.expand_path(@data["cache_path"])
11
- @prebuild_path = @data["prebuild_path"] || "Pods/_Prebuild"
11
+ @prebuild_path = @data["prebuild_path"] || "_Prebuild"
12
+ @prebuild_delta_path = @data["prebuild_delta_path"] || "_Prebuild_delta/changes.json"
13
+ end
14
+
15
+ def self.instance
16
+ @instance ||= new("PodBinaryCacheConfig.json")
12
17
  end
13
18
 
14
19
  def manifest_path(in_cache: false)
@@ -22,10 +27,5 @@ module PodPrebuild
22
27
  def generated_frameworks_dir(in_cache: false)
23
28
  root_dir(in_cache) + "/GeneratedFrameworks"
24
29
  end
25
-
26
- def delta_file_path
27
- # TODO (thuyen): Unify this path with PodPrebuild::Output#delta_file_path
28
- "Pods/_Prebuild_delta/changes.json"
29
- end
30
30
  end
31
31
  end
@@ -22,7 +22,7 @@ module PodPrebuild
22
22
  if Dir.exist?(dest_dir + "/.git")
23
23
  git("fetch origin #{branch}")
24
24
  git("checkout -f FETCH_HEAD", ignore_output: true)
25
- git("branch -D #{branch} || true", ignore_output: true, can_fail: true)
25
+ git("branch -D #{branch}", ignore_output: true, can_fail: true)
26
26
  git("checkout -b #{branch}")
27
27
  else
28
28
  FileUtils.rm_rf(dest_dir)
@@ -15,7 +15,7 @@ module PodPrebuild
15
15
  def run
16
16
  @fetcher.run
17
17
  prebuild
18
- changes = PodPrebuild::JSONFile.new(@config.delta_file_path)
18
+ changes = PodPrebuild::JSONFile.new(@config.prebuild_delta_path)
19
19
  return if changes.empty?
20
20
 
21
21
  sync_cache(changes)
@@ -12,7 +12,7 @@ module PodPrebuild
12
12
  commit_message = "Update prebuilt cache".shellescape
13
13
  git("add .")
14
14
  git("commit -m '#{commit_message}'")
15
- git("push origin head")
15
+ git("push origin #{@cache_branch}")
16
16
  end
17
17
  end
18
18
  end
@@ -0,0 +1,23 @@
1
+ require_relative "executor/pusher"
2
+
3
+ module Pod
4
+ class Command
5
+ class Binary < Command
6
+ class Push < Binary
7
+ self.arguments = [CLAide::Argument.new("CACHE-BRANCH", false)]
8
+
9
+ def initialize(argv)
10
+ super
11
+ @pusher = PodPrebuild::CachePusher.new(
12
+ config: prebuild_config,
13
+ cache_branch: argv.shift_argument || "master"
14
+ )
15
+ end
16
+
17
+ def run
18
+ @pusher.run
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods-binary-cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bang Nguyen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-03 00:00:00.000000000 Z
11
+ date: 2020-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cocoapods
@@ -115,6 +115,10 @@ files:
115
115
  - lib/cocoapods-binary-cache/cache/validator_with_podfile.rb
116
116
  - lib/cocoapods-binary-cache/dependencies_graph/dependencies_graph.rb
117
117
  - lib/cocoapods-binary-cache/dependencies_graph/graph_visualizer.rb
118
+ - lib/cocoapods-binary-cache/diagnosis/base.rb
119
+ - lib/cocoapods-binary-cache/diagnosis/diagnosis.rb
120
+ - lib/cocoapods-binary-cache/diagnosis/integration.rb
121
+ - lib/cocoapods-binary-cache/env.rb
118
122
  - lib/cocoapods-binary-cache/helper/benchmark_show.rb
119
123
  - lib/cocoapods-binary-cache/helper/checksum.rb
120
124
  - lib/cocoapods-binary-cache/helper/json.rb
@@ -147,7 +151,6 @@ files:
147
151
  - lib/cocoapods-binary-cache/pod-binary/tool/tool.rb
148
152
  - lib/cocoapods-binary-cache/pod-rome/LICENSE.txt
149
153
  - lib/cocoapods-binary-cache/pod-rome/build_framework.rb
150
- - lib/cocoapods-binary-cache/prebuild_cache.rb
151
154
  - lib/cocoapods-binary-cache/prebuild_output/metadata.rb
152
155
  - lib/cocoapods-binary-cache/prebuild_output/output.rb
153
156
  - lib/cocoapods-binary-cache/scheme_editor.rb
@@ -164,6 +167,7 @@ files:
164
167
  - lib/command/fetch.rb
165
168
  - lib/command/helper/zip.rb
166
169
  - lib/command/prebuild.rb
170
+ - lib/command/push.rb
167
171
  - lib/command/visualize.rb
168
172
  homepage: https://github.com/grab/cocoapods-binary-cache
169
173
  licenses:
@@ -184,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
188
  - !ruby/object:Gem::Version
185
189
  version: '0'
186
190
  requirements: []
187
- rubygems_version: 3.0.3
191
+ rubygems_version: 3.0.8
188
192
  signing_key:
189
193
  specification_version: 4
190
194
  summary: Reduce build time by building pod frameworks and cache to remote storage,
@@ -1,47 +0,0 @@
1
- # Copyright 2019 Grabtaxi Holdings PTE LTE (GRAB), All rights reserved.
2
- # Use of this source code is governed by an MIT-style license that can be found in the LICENSE file
3
-
4
- require 'json'
5
- require 'cocoapods'
6
- require_relative "helper/checksum"
7
-
8
- class PodCacheValidator
9
-
10
- # Cache miss/hit checking for development pods
11
- # Return 2 Hashes for cache miss and cache hit libraries
12
- def self.verify_devpod_checksum(sandbox_root, generated_framework_path, lock_file)
13
- devpod_path = "#{sandbox_root}/devpod/"
14
- target_path = generated_framework_path
15
- Pod::UI.puts "verify_devpod_checksum: #{devpod_path}"
16
- external_sources = lock_file.to_hash["EXTERNAL SOURCES"]
17
- unless File.directory?(target_path)
18
- FileUtils.mkdir_p(target_path)
19
- end
20
- missing_pods_dic = Hash[]
21
- cachehit_pods_dic = Hash[]
22
- if !external_sources
23
- Pod::UI.puts 'No development pods!'
24
- return missing_pods_dic, cachehit_pods
25
- end
26
- external_sources.each do |name, attribs|
27
- if attribs.class == Hash
28
- path = attribs[:path]
29
- if path
30
- hash = FolderChecksum.checksum(path)
31
- cached_path = "#{devpod_path}#{name}_#{hash}"
32
- if !Dir.exists?(cached_path)
33
- missing_pods_dic[name] = hash
34
- else
35
- cachehit_pods_dic[name] = hash
36
- target_dir = "#{target_path}/#{name}"
37
- FileUtils.rm_r(target_dir, :force => true)
38
- FileUtils.cp_r(cached_path, target_dir)
39
- end
40
- end
41
- else
42
- Pod::UI.puts "Error, wrong type: #{attribs}"
43
- end
44
- end
45
- return missing_pods_dic, cachehit_pods_dic
46
- end
47
- end