cocoapods-binary-cache 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
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