cocoapods-binary-ht 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/cocoapods-binary-cache.rb +2 -0
- data/lib/cocoapods-binary-ht/cache/all.rb +9 -0
- data/lib/cocoapods-binary-ht/cache/validation_result.rb +73 -0
- data/lib/cocoapods-binary-ht/cache/validator.rb +20 -0
- data/lib/cocoapods-binary-ht/cache/validator_accumulated.rb +4 -0
- data/lib/cocoapods-binary-ht/cache/validator_base.rb +112 -0
- data/lib/cocoapods-binary-ht/cache/validator_dependencies_graph.rb +25 -0
- data/lib/cocoapods-binary-ht/cache/validator_dev_pods.rb +30 -0
- data/lib/cocoapods-binary-ht/cache/validator_exclusion.rb +14 -0
- data/lib/cocoapods-binary-ht/cache/validator_non_dev_pods.rb +13 -0
- data/lib/cocoapods-binary-ht/cache/validator_with_podfile.rb +9 -0
- data/lib/cocoapods-binary-ht/dependencies_graph/dependencies_graph.rb +108 -0
- data/lib/cocoapods-binary-ht/dependencies_graph/graph_visualizer.rb +65 -0
- data/lib/cocoapods-binary-ht/diagnosis/base.rb +13 -0
- data/lib/cocoapods-binary-ht/diagnosis/diagnosis.rb +24 -0
- data/lib/cocoapods-binary-ht/diagnosis/integration.rb +23 -0
- data/lib/cocoapods-binary-ht/env.rb +32 -0
- data/lib/cocoapods-binary-ht/helper/benchmark_show.rb +11 -0
- data/lib/cocoapods-binary-ht/helper/checksum.rb +18 -0
- data/lib/cocoapods-binary-ht/helper/json.rb +37 -0
- data/lib/cocoapods-binary-ht/helper/lockfile.rb +90 -0
- data/lib/cocoapods-binary-ht/helper/path_utils.rb +8 -0
- data/lib/cocoapods-binary-ht/helper/podspec.rb +20 -0
- data/lib/cocoapods-binary-ht/hooks/post_install.rb +23 -0
- data/lib/cocoapods-binary-ht/hooks/pre_install.rb +121 -0
- data/lib/cocoapods-binary-ht/main.rb +21 -0
- data/lib/cocoapods-binary-ht/pod-binary/LICENSE.txt +22 -0
- data/lib/cocoapods-binary-ht/pod-binary/helper/build.rb +37 -0
- data/lib/cocoapods-binary-ht/pod-binary/helper/detected_prebuilt_pods/installer.rb +25 -0
- data/lib/cocoapods-binary-ht/pod-binary/helper/detected_prebuilt_pods/target_definition.rb +29 -0
- data/lib/cocoapods-binary-ht/pod-binary/helper/names.rb +27 -0
- data/lib/cocoapods-binary-ht/pod-binary/helper/podfile_options.rb +2 -0
- data/lib/cocoapods-binary-ht/pod-binary/helper/prebuild_sandbox.rb +71 -0
- data/lib/cocoapods-binary-ht/pod-binary/helper/sandbox.rb +9 -0
- data/lib/cocoapods-binary-ht/pod-binary/helper/target_checker.rb +42 -0
- data/lib/cocoapods-binary-ht/pod-binary/integration/alter_specs.rb +150 -0
- data/lib/cocoapods-binary-ht/pod-binary/integration/patch/embed_framework_script.rb +36 -0
- data/lib/cocoapods-binary-ht/pod-binary/integration/patch/resolve_dependencies.rb +20 -0
- data/lib/cocoapods-binary-ht/pod-binary/integration/patch/sandbox_analyzer_state.rb +29 -0
- data/lib/cocoapods-binary-ht/pod-binary/integration/patch/source_installation.rb +55 -0
- data/lib/cocoapods-binary-ht/pod-binary/integration/source_installer.rb +114 -0
- data/lib/cocoapods-binary-ht/pod-binary/integration/validation.rb +20 -0
- data/lib/cocoapods-binary-ht/pod-binary/integration.rb +11 -0
- data/lib/cocoapods-binary-ht/pod-binary/prebuild.rb +166 -0
- data/lib/cocoapods-binary-ht/pod-binary/prebuild_dsl.rb +10 -0
- data/lib/cocoapods-binary-ht/pod-binary/prebuild_hook.rb +10 -0
- data/lib/cocoapods-binary-ht/pod-rome/LICENSE.txt +22 -0
- data/lib/cocoapods-binary-ht/pod-rome/xcodebuild_command.rb +266 -0
- data/lib/cocoapods-binary-ht/pod-rome/xcodebuild_raw.rb +68 -0
- data/lib/cocoapods-binary-ht/prebuild_output/metadata.rb +63 -0
- data/lib/cocoapods-binary-ht/prebuild_output/output.rb +44 -0
- data/lib/cocoapods-binary-ht/state_store.rb +21 -0
- data/lib/cocoapods-binary-ht/ui.rb +9 -0
- data/lib/cocoapods_plugin.rb +5 -0
- data/lib/command/binary.rb +37 -0
- data/lib/command/config.rb +215 -0
- data/lib/command/executor/base.rb +37 -0
- data/lib/command/executor/fetcher.rb +67 -0
- data/lib/command/executor/prebuilder.rb +61 -0
- data/lib/command/executor/pusher.rb +35 -0
- data/lib/command/executor/visualizer.rb +23 -0
- data/lib/command/fetch.rb +22 -0
- data/lib/command/helper/zip.rb +20 -0
- data/lib/command/prebuild.rb +47 -0
- data/lib/command/push.rb +22 -0
- data/lib/command/visualize.rb +34 -0
- metadata +209 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8fb1e861e5728064394631f9037d1b7d164ee4385f5dc5bd768bae537aa9c5eb
|
4
|
+
data.tar.gz: 820ba6fd23aa548cbebc2de961ef4805fde49d3ea49838c2936cf51c78378829
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 10aa6a928916f62360f0a705a461b487623205df3f6369a22eb21101a886febc774ada9626caf0bdd788ac5f6d972fb0deb2d5417f6f89c125a3b3883d837faf
|
7
|
+
data.tar.gz: aee491cdcc6e53f549aa7cac39074c55614eb3a843c81347255578551cca8d6b77a4d1c8c07d8d635b2648a33d0c33b79e999d7646cbf4603de1eea8eaf22284
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require_relative "validation_result"
|
2
|
+
require_relative "validator_base"
|
3
|
+
require_relative "validator_accumulated"
|
4
|
+
require_relative "validator_with_podfile"
|
5
|
+
require_relative "validator_non_dev_pods"
|
6
|
+
require_relative "validator_dev_pods"
|
7
|
+
require_relative "validator_dependencies_graph"
|
8
|
+
require_relative "validator_exclusion"
|
9
|
+
require_relative "validator"
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module PodPrebuild
|
2
|
+
class CacheValidationResult
|
3
|
+
attr_reader :hit, :missed_with_reasons
|
4
|
+
|
5
|
+
def initialize(missed_with_reasons = {}, hit = Set.new)
|
6
|
+
@missed_with_reasons = missed_with_reasons
|
7
|
+
@hit = hit.to_set - missed_with_reasons.keys
|
8
|
+
end
|
9
|
+
|
10
|
+
def all
|
11
|
+
(hit + missed).to_set
|
12
|
+
end
|
13
|
+
|
14
|
+
def missed
|
15
|
+
@missed_with_reasons.keys.to_set
|
16
|
+
end
|
17
|
+
|
18
|
+
def missed?(name)
|
19
|
+
@missed_with_reasons.key?(name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def hit?(name)
|
23
|
+
@hit.include?(name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def include?(name)
|
27
|
+
missed?(name) || hit?(name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def merge(other)
|
31
|
+
PodPrebuild::CacheValidationResult.new(
|
32
|
+
@missed_with_reasons.merge(other.missed_with_reasons),
|
33
|
+
@hit + other.hit
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_to(path)
|
38
|
+
FileUtils.mkdir_p(File.dirname(path))
|
39
|
+
json_file = PodPrebuild::JSONFile.new(path)
|
40
|
+
json_file["cache_missed"] = missed.to_a
|
41
|
+
json_file["cache_hit"] = hit.to_a
|
42
|
+
json_file.save!
|
43
|
+
end
|
44
|
+
|
45
|
+
def keep(names)
|
46
|
+
base_names = names.map { |name| name.split("/")[0] }.to_set
|
47
|
+
select { |name| base_names.include?(name.split("/")[0]) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def discard(names)
|
51
|
+
base_names = names.map { |name| name.split("/")[0] }.to_set
|
52
|
+
reject { |name| base_names.include?(name.split("/")[0]) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def select(&predicate)
|
56
|
+
PodPrebuild::CacheValidationResult.new(
|
57
|
+
@missed_with_reasons.select { |name, _| predicate.call(name) },
|
58
|
+
@hit.select(&predicate)
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def reject(&predicate)
|
63
|
+
select { |name| !predicate.call(name) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def print_summary
|
67
|
+
Pod::UI.puts "Cache validation: hit (#{@hit.count}) #{@hit.to_a}"
|
68
|
+
@missed_with_reasons.each do |name, reason|
|
69
|
+
Pod::UI.puts "Cache validation: missed #{name}. Reason: #{reason}".yellow
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module PodPrebuild
|
2
|
+
class CacheValidator
|
3
|
+
def initialize(options)
|
4
|
+
@validators = [
|
5
|
+
PodPrebuild::PodfileChangesCacheValidator.new(options),
|
6
|
+
PodPrebuild::NonDevPodsCacheValidator.new(options)
|
7
|
+
]
|
8
|
+
@validators << PodPrebuild::DevPodsCacheValidator.new(options) if PodPrebuild.config.dev_pods_enabled?
|
9
|
+
@validators << PodPrebuild::DependenciesGraphCacheValidator.new(options)
|
10
|
+
@validators << PodPrebuild::ExclusionCacheValidator.new(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate(*)
|
14
|
+
@validators.reduce(PodPrebuild::CacheValidationResult.new) do |acc, validator|
|
15
|
+
validation = validator.validate(acc)
|
16
|
+
validator.is_a?(AccumulatedCacheValidator) ? validation : acc.merge(validation)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module PodPrebuild
|
2
|
+
class BaseCacheValidator
|
3
|
+
attr_reader :podfile, :pod_lockfile, :prebuilt_lockfile
|
4
|
+
attr_reader :validate_prebuilt_settings, :generated_framework_path
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
@podfile = options[:podfile]
|
8
|
+
@pod_lockfile = options[:pod_lockfile] && PodPrebuild::Lockfile.new(options[:pod_lockfile])
|
9
|
+
@prebuilt_lockfile = options[:prebuilt_lockfile] && PodPrebuild::Lockfile.new(options[:prebuilt_lockfile])
|
10
|
+
@validate_prebuilt_settings = options[:validate_prebuilt_settings]
|
11
|
+
@generated_framework_path = options[:generated_framework_path]
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate(*)
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
def changes_of_prebuilt_lockfile_vs_podfile
|
19
|
+
@changes_of_prebuilt_lockfile_vs_podfile ||= Pod::Installer::Analyzer::SpecsState.new(
|
20
|
+
@prebuilt_lockfile.lockfile.detect_changes_with_podfile(@podfile)
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate_with_podfile
|
25
|
+
changes = changes_of_prebuilt_lockfile_vs_podfile
|
26
|
+
missed = changes.added.map { |pod| [pod, "Added from Podfile"] }.to_h
|
27
|
+
missed.merge!(changes.changed.map { |pod| [pod, "Updated from Podfile"] }.to_h)
|
28
|
+
PodPrebuild::CacheValidationResult.new(missed, changes.unchanged)
|
29
|
+
end
|
30
|
+
|
31
|
+
def validate_pods(options)
|
32
|
+
pods = options[:pods]
|
33
|
+
subspec_pods = options[:subspec_pods]
|
34
|
+
prebuilt_pods = options[:prebuilt_pods]
|
35
|
+
|
36
|
+
missed = {}
|
37
|
+
hit = Set.new
|
38
|
+
|
39
|
+
check_pod = lambda do |name|
|
40
|
+
root_name = name.split("/")[0]
|
41
|
+
version = pods[name]
|
42
|
+
prebuilt_version = prebuilt_pods[name]
|
43
|
+
result = false
|
44
|
+
if prebuilt_version.nil?
|
45
|
+
missed[name] = "Not available (#{version})"
|
46
|
+
elsif prebuilt_version != version
|
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)"
|
50
|
+
else
|
51
|
+
diff = incompatible_pod(root_name)
|
52
|
+
if diff.empty?
|
53
|
+
hit << name
|
54
|
+
result = true
|
55
|
+
else
|
56
|
+
missed[name] = "Incompatible: #{diff}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
result
|
60
|
+
end
|
61
|
+
|
62
|
+
subspec_pods.each do |parent, children|
|
63
|
+
missed_children = children.reject { |child| check_pod.call(child) }
|
64
|
+
if missed_children.empty?
|
65
|
+
hit << parent
|
66
|
+
else
|
67
|
+
missed[parent] = "Subspec pods were missed: #{missed_children}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
non_subspec_pods = pods.reject { |pod| subspec_pods.include?(pod) }
|
72
|
+
non_subspec_pods.each { |pod, _| check_pod.call(pod) }
|
73
|
+
PodPrebuild::CacheValidationResult.new(missed, hit)
|
74
|
+
end
|
75
|
+
|
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)
|
80
|
+
end
|
81
|
+
|
82
|
+
def incompatible_build_settings(name)
|
83
|
+
settings_diff = {}
|
84
|
+
prebuilt_build_settings = read_prebuilt_build_settings(name)
|
85
|
+
validate_prebuilt_settings&.(name)&.each do |key, value|
|
86
|
+
prebuilt_value = prebuilt_build_settings[key]
|
87
|
+
unless prebuilt_value.nil? || value == prebuilt_value
|
88
|
+
settings_diff[key] = { :current => value, :prebuilt => prebuilt_value }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
settings_diff
|
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
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module PodPrebuild
|
2
|
+
class DependenciesGraphCacheValidator < AccumulatedCacheValidator
|
3
|
+
def initialize(options)
|
4
|
+
super(options)
|
5
|
+
@ignored_pods = options[:ignored_pods] || Set.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def validate(accumulated)
|
9
|
+
return accumulated if library_evolution_supported? || @pod_lockfile.nil?
|
10
|
+
|
11
|
+
dependencies_graph = DependenciesGraph.new(lockfile: @pod_lockfile.lockfile, invert_edge: true)
|
12
|
+
clients = dependencies_graph.get_clients(accumulated.discard(@ignored_pods).missed.to_a)
|
13
|
+
unless PodPrebuild.config.dev_pods_enabled?
|
14
|
+
clients = clients.reject { |client| @pod_lockfile.dev_pods.keys.include?(client) }
|
15
|
+
end
|
16
|
+
|
17
|
+
missed = clients.map { |client| [client, "Dependencies were missed"] }.to_h
|
18
|
+
accumulated.merge(PodPrebuild::CacheValidationResult.new(missed, Set.new))
|
19
|
+
end
|
20
|
+
|
21
|
+
def library_evolution_supported?
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module PodPrebuild
|
2
|
+
class DevPodsCacheValidator < BaseCacheValidator
|
3
|
+
def validate(*)
|
4
|
+
return PodPrebuild::CacheValidationResult.new if @pod_lockfile.nil?
|
5
|
+
|
6
|
+
validate_pods(
|
7
|
+
pods: @pod_lockfile.dev_pods,
|
8
|
+
subspec_pods: [],
|
9
|
+
prebuilt_pods: @prebuilt_lockfile.nil? ? {} : @prebuilt_lockfile.dev_pods
|
10
|
+
)
|
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
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module PodPrebuild
|
2
|
+
class ExclusionCacheValidator < AccumulatedCacheValidator
|
3
|
+
def initialize(options)
|
4
|
+
super(options)
|
5
|
+
@ignored_pods = options[:ignored_pods] || Set.new
|
6
|
+
@prebuilt_pod_names = options[:prebuilt_pod_names]
|
7
|
+
end
|
8
|
+
|
9
|
+
def validate(accumulated)
|
10
|
+
validation = @prebuilt_pod_names.nil? ? accumulated : accumulated.keep(@prebuilt_pod_names)
|
11
|
+
validation.discard(@ignored_pods)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module PodPrebuild
|
2
|
+
class NonDevPodsCacheValidator < BaseCacheValidator
|
3
|
+
def validate(*)
|
4
|
+
return PodPrebuild::CacheValidationResult.new if @pod_lockfile.nil?
|
5
|
+
|
6
|
+
validate_pods(
|
7
|
+
pods: @pod_lockfile.non_dev_pods,
|
8
|
+
subspec_pods: @pod_lockfile.subspec_vendor_pods,
|
9
|
+
prebuilt_pods: @prebuilt_lockfile.nil? ? {} : @prebuilt_lockfile.non_dev_pods
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# Copyright 2019 panda Holdings PTE LTE (panda), 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 "rgl/adjacency"
|
5
|
+
require "rgl/dot"
|
6
|
+
require_relative "graph_visualizer"
|
7
|
+
|
8
|
+
# Using RGL graph because GraphViz doesn't store adjacent of a node/vertex
|
9
|
+
# but we need to traverse a substree from any node
|
10
|
+
# https://github.com/monora/rgl/blob/master/lib/rgl/adjacency.rb
|
11
|
+
|
12
|
+
class DependenciesGraph
|
13
|
+
def initialize(options)
|
14
|
+
@lockfile = options[:lockfile]
|
15
|
+
@devpod_only = options[:devpod_only]
|
16
|
+
@max_deps = options[:max_deps].to_i if options[:max_deps]
|
17
|
+
# A normal edge is an edge (one direction) from library A to library B which is a dependency of A.
|
18
|
+
@invert_edge = options[:invert_edge] || false
|
19
|
+
end
|
20
|
+
|
21
|
+
# Input : a list of library names.
|
22
|
+
# Output: a set of library names which are clients (directly and indirectly) of those input libraries.
|
23
|
+
def get_clients(libnames)
|
24
|
+
result = Set.new
|
25
|
+
libnames.each do |lib|
|
26
|
+
if graph.has_vertex?(lib)
|
27
|
+
result.merge(traverse_sub_tree(graph, lib))
|
28
|
+
else
|
29
|
+
Pod::UI.puts "Warning: cannot find lib: #{lib}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
result
|
33
|
+
end
|
34
|
+
|
35
|
+
def write_graphic_file(options)
|
36
|
+
graph.write_to_graphic_file(options)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def dependencies
|
42
|
+
@dependencies ||= (@lockfile && @lockfile.to_hash["PODS"])
|
43
|
+
end
|
44
|
+
|
45
|
+
def dev_pod_sources
|
46
|
+
@dev_pod_sources ||= @lockfile.to_hash["EXTERNAL SOURCES"].select { |_, attributes| attributes.key?(:path) } || {}
|
47
|
+
end
|
48
|
+
|
49
|
+
# Convert array of dictionaries -> a dictionary with format {A: [A's dependencies]}
|
50
|
+
def pod_to_dependencies
|
51
|
+
dependencies
|
52
|
+
.map { |d| d.is_a?(Hash) ? d : { d => [] } }
|
53
|
+
.reduce({}) { |combined, individual| combined.merge!(individual) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_vertex(graph, pod)
|
57
|
+
node_name = sanitized_pod_name(pod)
|
58
|
+
return if @devpod_only && dev_pod_sources[node_name].nil?
|
59
|
+
|
60
|
+
graph.add_vertex(node_name)
|
61
|
+
node_name
|
62
|
+
end
|
63
|
+
|
64
|
+
def sanitized_pod_name(name)
|
65
|
+
Pod::Dependency.from_string(name).name
|
66
|
+
end
|
67
|
+
|
68
|
+
def reach_max_deps(deps)
|
69
|
+
return unless @max_deps
|
70
|
+
return deps.count > @max_deps unless @devpod_only
|
71
|
+
|
72
|
+
deps = deps.reject { |name| dev_pod_sources[name].nil? }
|
73
|
+
deps.count > @max_deps
|
74
|
+
end
|
75
|
+
|
76
|
+
def graph
|
77
|
+
@graph ||= begin
|
78
|
+
graph = RGL::DirectedAdjacencyGraph.new
|
79
|
+
pod_to_dependencies.each do |pod, dependencies|
|
80
|
+
next if reach_max_deps(dependencies)
|
81
|
+
|
82
|
+
pod_node = add_vertex(graph, pod)
|
83
|
+
next if pod_node.nil?
|
84
|
+
|
85
|
+
dependencies.each do |dependency|
|
86
|
+
dep_node = add_vertex(graph, dependency)
|
87
|
+
next if dep_node.nil?
|
88
|
+
|
89
|
+
if @invert_edge
|
90
|
+
graph.add_edge(dep_node, pod_node)
|
91
|
+
else
|
92
|
+
graph.add_edge(pod_node, dep_node)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
graph
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def traverse_sub_tree(graph, vertex)
|
101
|
+
visited_nodes = Set.new
|
102
|
+
graph.each_adjacent(vertex) do |v|
|
103
|
+
visited_nodes.add(v)
|
104
|
+
visited_nodes.merge(traverse_sub_tree(graph, v))
|
105
|
+
end
|
106
|
+
visited_nodes
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Copyright 2019 panda Holdings PTE LTE (panda), 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
|
+
# https://github.com/monora/rgl/blob/0b526e16f9fb344abf387f4c5523d7917ce8f4b1/lib/rgl/dot.rb
|
4
|
+
|
5
|
+
require "rgl/rdot"
|
6
|
+
|
7
|
+
module RGL
|
8
|
+
module Graph
|
9
|
+
def to_dot_graph(options)
|
10
|
+
highlight_nodes = options[:highlight_nodes] || Set.new
|
11
|
+
options["name"] ||= self.class.name.gsub(/:/, "_")
|
12
|
+
fontsize = options["fontsize"] || "12"
|
13
|
+
graph = (directed? ? DOT::Digraph : DOT::Graph).new(options)
|
14
|
+
edge_class = directed? ? DOT::DirectedEdge : DOT::Edge
|
15
|
+
vertex_options = options["vertex"] || {}
|
16
|
+
edge_options = options["edge"] || {}
|
17
|
+
|
18
|
+
each_vertex do |v|
|
19
|
+
default_vertex_options = {
|
20
|
+
"name" => vertex_id(v),
|
21
|
+
"fontsize" => fontsize,
|
22
|
+
"label" => vertex_label(v),
|
23
|
+
"style" => "filled"
|
24
|
+
}
|
25
|
+
default_vertex_options.merge!("color" => "red", "fillcolor" => "red") if highlight_nodes.include?(v)
|
26
|
+
each_vertex_options = default_vertex_options.merge(vertex_options)
|
27
|
+
vertex_options.each { |option, val| each_vertex_options[option] = val.call(v) if val.is_a?(Proc) }
|
28
|
+
graph << DOT::Node.new(each_vertex_options)
|
29
|
+
end
|
30
|
+
|
31
|
+
each_edge do |u, v|
|
32
|
+
default_edge_options = {
|
33
|
+
"from" => vertex_id(u),
|
34
|
+
"to" => vertex_id(v),
|
35
|
+
"fontsize" => fontsize
|
36
|
+
}
|
37
|
+
each_edge_options = default_edge_options.merge(edge_options)
|
38
|
+
edge_options.each { |option, val| each_edge_options[option] = val.call(u, v) if val.is_a?(Proc) }
|
39
|
+
graph << edge_class.new(each_edge_options)
|
40
|
+
end
|
41
|
+
|
42
|
+
graph
|
43
|
+
end
|
44
|
+
|
45
|
+
def write_to_graphic_file(options)
|
46
|
+
output_path = Pathname.new(options[:output_path])
|
47
|
+
fmt = output_path.extname.delete_prefix(".")
|
48
|
+
dotfile = output_path.sub_ext(".dot")
|
49
|
+
|
50
|
+
File.open(dotfile, "w") do |f|
|
51
|
+
f << to_dot_graph(options).to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
unless system("dot -T#{fmt} #{dotfile} -o #{output_path}")
|
55
|
+
message = <<~HEREDOC
|
56
|
+
Error executing dot. Did you install GraphViz?
|
57
|
+
Try installing it via Homebrew: `brew install graphviz`.
|
58
|
+
Visit https://graphviz.org/download/ for more installation instructions.
|
59
|
+
HEREDOC
|
60
|
+
raise message
|
61
|
+
end
|
62
|
+
output_path
|
63
|
+
end
|
64
|
+
end
|
65
|
+
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,24 @@
|
|
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
|
+
diagnosis = @diagnosers.map(&:run)
|
14
|
+
errors = diagnosis.select { |d| d[0] == :error }.map { |d| d[1] }
|
15
|
+
warnings = diagnosis.select { |d| d[0] == :error }.map { |d| d[1] }
|
16
|
+
|
17
|
+
warnings.each { |d| Pod::UI.puts "⚠️ #{d[1]}" }
|
18
|
+
errors.each { |d| Pod::UI.puts "🚩 #{d[1]}" }
|
19
|
+
return if errors.empty? || !PodPrebuild.config.strict_diagnosis?
|
20
|
+
|
21
|
+
raise "There are #{errors.count} error(s) spotted after the diagnosis"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
3
|
+
module PodPrebuild
|
4
|
+
class IntegrationDiagnosis < BaseDiagnosis
|
5
|
+
def run
|
6
|
+
should_be_integrated = if PodPrebuild.config.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 = \
|
14
|
+
@standard_sandbox.pod_dir(name) + \
|
15
|
+
PodPrebuild.config.prebuilt_path(path: "#{module_name}.framework")
|
16
|
+
framework_path.exist?
|
17
|
+
end
|
18
|
+
return [] if unintegrated.empty?
|
19
|
+
|
20
|
+
[[:error, "Unintegrated frameworks: #{unintegrated}"]]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
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 ||= PodPrebuild.config.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
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Copyright 2019 panda Holdings PTE LTE (panda), 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 "benchmark"
|
5
|
+
|
6
|
+
class BenchmarkShow
|
7
|
+
def self.benchmark
|
8
|
+
time = Benchmark.measure { yield }
|
9
|
+
Pod::UI.puts "🕛 Time elapsed: #{time}"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Copyright 2019 panda Holdings PTE LTE (panda), 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 "digest/md5"
|
5
|
+
|
6
|
+
class FolderChecksum
|
7
|
+
def self.git_checksum(dir)
|
8
|
+
checksum_of_files(`git ls-files #{File.realdirpath(dir).shellescape}`.split("\n"))
|
9
|
+
rescue => e
|
10
|
+
Pod::UI.warn "Cannot get checksum of tracked files under #{dir}: #{e}"
|
11
|
+
checksum_of_files(Dir["#{dir}/**/*"].reject { |f| File.directory?(f) })
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.checksum_of_files(files)
|
15
|
+
checksums = files.sort.map { |f| Digest::MD5.hexdigest(File.read(f)) }
|
16
|
+
Digest::MD5.hexdigest(checksums.join)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module PodPrebuild
|
4
|
+
class JSONFile
|
5
|
+
attr_reader :path
|
6
|
+
attr_reader :data
|
7
|
+
|
8
|
+
def initialize(path)
|
9
|
+
@path = path
|
10
|
+
@data = load_json
|
11
|
+
end
|
12
|
+
|
13
|
+
def empty?
|
14
|
+
@data.empty?
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](key)
|
18
|
+
@data[key]
|
19
|
+
end
|
20
|
+
|
21
|
+
def []=(key, value)
|
22
|
+
@data[key] = value
|
23
|
+
end
|
24
|
+
|
25
|
+
def save!
|
26
|
+
File.open(@path, "w") { |f| f.write(JSON.pretty_generate(@data)) }
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def load_json
|
32
|
+
File.open(@path) { |f| JSON.parse(f.read) }
|
33
|
+
rescue
|
34
|
+
{}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|