xcode-archive-cache 0.0.8.pre.2 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52f8f43f53d74aef2d09148fe876d585c3cacf6f8f280a493684e235fb718d7f
4
- data.tar.gz: 71df654b2b3d8e4bc867357b83e86bf6f2aea403f9d15c2552bdefe1d3688331
3
+ metadata.gz: ff86c853bc7b50f265964695cd55edd14821c821f5d27a1f916dcc23ccc1c4b4
4
+ data.tar.gz: a11e6dd9c98f59526f6f5329aab00acdcc58b5d7e2b65d83b6a1348d647a2323
5
5
  SHA512:
6
- metadata.gz: a2e2ebc240b6ec293000cc023e65ed11a563ba841cb3dfafbab7e8d1ceaae0d9a21d2d9d0b556ff450495be9f20384adb27b34f68614f716aedf1e1aab9c28e4
7
- data.tar.gz: 472d0209a2a24f01c8f07a7e33bdafbd85d915dbfd358f1f0799ca47ba3b34456f11d09ba67bc38874b95452f8e88d2e6540ae3ed5ab654a9cc6206a5d51cc64
6
+ metadata.gz: a71f194f4af63d93ee4f256977eb98525065599a36f270215c5c0f3a18cb8742957bb8f2e407497a7629f05ba18b9532d093d02b1dec305fcf4f82f815473431
7
+ data.tar.gz: ba25058d81d37e12594422d9a765d07fb8af192b53fe980ca3b4da3e1eac61f5a0bc69454f406be92094742e7809dbe8f4887d33e48b305c869733e5c581a4d8
@@ -9,7 +9,8 @@ module XcodeArchiveCache
9
9
  #
10
10
  def archive(path, destination)
11
11
  if File.exists?(destination)
12
- raise ArgumentError.new, "Artifact cache path #{destination} is already taken"
12
+ warn "Replacing artifact archive at path #{destination}"
13
+ FileUtils.rm_rf(destination)
13
14
  end
14
15
 
15
16
  if File.file?(path)
@@ -60,7 +60,8 @@ module XcodeArchiveCache
60
60
  state_file_path = archive_path + ".state"
61
61
 
62
62
  if File.exist?(state_file_path)
63
- raise ArgumentError.new, "State file already exists: #{state_file_path}"
63
+ warn "Replacing state file #{state_file_path}"
64
+ FileUtils.rm_f(state_file_path)
64
65
  end
65
66
 
66
67
  dependency_shas = node.dependencies
@@ -35,7 +35,7 @@ module XcodeArchiveCache
35
35
  # @param [XcodeArchiveCache::BuildGraph::Graph] graph
36
36
  #
37
37
  def should_rebuild?(graph)
38
- graph.nodes.reduce(false) {|rebuild, node| rebuild || node.waiting_for_rebuild}
38
+ graph.root_node.state != :unpacked
39
39
  end
40
40
 
41
41
  private
@@ -2,6 +2,8 @@ module XcodeArchiveCache
2
2
  module Build
3
3
  class ProductExtractor
4
4
 
5
+ include XcodeArchiveCache::Logs
6
+
5
7
  # @param [String] configuration
6
8
  # @param [String] derived_data_path
7
9
  #
@@ -17,7 +19,9 @@ module XcodeArchiveCache
17
19
  #
18
20
  def list_product_contents(built_node)
19
21
  file_paths = list_products(built_node)
20
- file_paths.select {|path| File.exist?(path)}.map {|path| File.realpath(path)}
22
+ file_paths
23
+ .select { |path| File.exist?(path) }
24
+ .map { |path| File.realpath(path) }
21
25
  end
22
26
 
23
27
  private
@@ -78,7 +82,39 @@ module XcodeArchiveCache
78
82
  raise Informative, "Product of type #{built_node.native_target.product_type} not found for #{built_node.name}"
79
83
  end
80
84
 
81
- [product_path]
85
+ paths = [product_path]
86
+
87
+ # this one is generated during Swift compilation
88
+ # so we need to cache it as well
89
+ #
90
+ swift_objc_interface_header_glob = get_swift_objc_interface_header_glob(built_node)
91
+ swift_objc_interface_header_path = Dir.glob(swift_objc_interface_header_glob).first
92
+ if swift_objc_interface_header_path
93
+ debug("using Swift-ObjC interface header #{swift_objc_interface_header_path}")
94
+ paths << swift_objc_interface_header_path
95
+ end
96
+
97
+ swiftmodule_glob = get_swiftmodule_glob(built_node)
98
+ if swiftmodule_glob
99
+ swiftmodule_path = Dir.glob(swiftmodule_glob).first
100
+
101
+ if swiftmodule_path
102
+ debug("using swiftmodule #{swiftmodule_path}")
103
+ paths << swiftmodule_path
104
+ end
105
+ end
106
+
107
+ modulemap_glob = get_modulemap_glob(built_node)
108
+ if modulemap_glob
109
+ modulemap_path = Dir.glob(modulemap_glob).first
110
+
111
+ if modulemap_path
112
+ debug("using modulemap #{modulemap_path}")
113
+ paths << modulemap_path
114
+ end
115
+ end
116
+
117
+ paths
82
118
  end
83
119
 
84
120
  # @param [XcodeArchiveCache::BuildGraph::Node] built_node
@@ -89,9 +125,52 @@ module XcodeArchiveCache
89
125
  product_name = built_node.native_target.product_reference.name ?
90
126
  built_node.native_target.product_reference.name :
91
127
  built_node.native_target.product_reference.path
128
+ get_product_glob(File.basename(product_name))
129
+ end
130
+
131
+ # @param [XcodeArchiveCache::BuildGraph::Node] built_node
132
+ #
133
+ # @return [String]
134
+ #
135
+ def get_swift_objc_interface_header_glob(built_node)
136
+ get_product_glob(File.basename(built_node.swift_objc_interface_header_file))
137
+ end
138
+
139
+ # @param [XcodeArchiveCache::BuildGraph::Node] built_node
140
+ #
141
+ # @return [String]
142
+ #
143
+ def get_swiftmodule_glob(built_node)
144
+ if built_node.module_name
145
+ get_product_glob(built_node.module_name + ".swiftmodule")
146
+ end
147
+ end
148
+
149
+ # @param [XcodeArchiveCache::BuildGraph::Node] built_node
150
+ #
151
+ # @return [String]
152
+ #
153
+ def get_modulemap_glob(built_node)
154
+ resulting_modulemap_file_name = built_node.resulting_modulemap_file_name
155
+ if resulting_modulemap_file_name
156
+ get_product_glob(resulting_modulemap_file_name)
157
+ else
158
+ modulemap_file_path = built_node.original_modulemap_file_path
159
+ if modulemap_file_path && File.exist?(modulemap_file_path)
160
+ modulemap_file_name = File.basename(modulemap_file_path)
161
+ get_product_glob(modulemap_file_name)
162
+ end
163
+ end
164
+ end
165
+
166
+ # @param [String] file_name
167
+ #
168
+ # @return [String]
169
+ #
170
+ def get_product_glob(file_name)
92
171
  File.join(derived_data_path,
93
172
  "**",
94
- File.basename(product_name))
173
+ file_name)
95
174
  end
96
175
 
97
176
  # @param [String] framework_path
@@ -106,7 +185,7 @@ module XcodeArchiveCache
106
185
  end
107
186
 
108
187
  uuids = list_bc_symbolmap_uuids(executable_path)
109
- uuids.map {|uuid| find_bc_symbolmap(uuid)}.flatten
188
+ uuids.map { |uuid| find_bc_symbolmap(uuid) }.flatten
110
189
  end
111
190
 
112
191
  # @param [String] executable_path
@@ -114,7 +193,11 @@ module XcodeArchiveCache
114
193
  # @return [Array<String>]
115
194
  #
116
195
  def list_bc_symbolmap_uuids(executable_path)
117
- shell_executor.execute_for_output("otool -l #{executable_path} | grep uuid | awk {'print $2'}").split("\n")
196
+ begin
197
+ shell_executor.execute_for_output("otool -l #{executable_path} | grep uuid | awk {'print $2'}").split("\n")
198
+ rescue
199
+ []
200
+ end
118
201
  end
119
202
 
120
203
  # @param [String] uuid
@@ -67,7 +67,11 @@ module XcodeArchiveCache
67
67
  node = ALL_NODES.select {|node| node.native_target.uuid == target.uuid && node.native_target.project == target.project}.first
68
68
  if node
69
69
  debug("already traversed this one")
70
- graph.add_multiple_nodes(node.subgraph) unless graph.nodes.include?(node)
70
+ unless graph.nodes.include?(node)
71
+ nodes_to_add = node.subgraph.select {|subgraph_node| !graph.nodes.include?(subgraph_node)}
72
+ graph.add_multiple_nodes(nodes_to_add)
73
+ end
74
+
71
75
  return node
72
76
  else
73
77
  debug("adding new node")
@@ -5,13 +5,22 @@ module XcodeArchiveCache
5
5
  # @param [Array<Xcodeproj::Project>] projects
6
6
  #
7
7
  def initialize(projects)
8
- @all_targets = projects
9
- .map {|project| unnest(project)}
10
- .flatten
11
- .uniq
12
- .map(&:native_targets)
13
- .flatten
14
- .select {|target| !target.test_target_type? }
8
+ @all_targets = extract_targets(projects)
9
+ end
10
+
11
+ # @param [Array<Xcodeproj::Project>] projects
12
+ #
13
+ # @return [Array<Xcodeproj::Project::Object::PBXNativeTarget>]
14
+ #
15
+ def extract_targets(projects)
16
+ projects
17
+ .map {|project| unnest(project)}
18
+ .flatten
19
+ .sort_by(&:path)
20
+ .inject([]) {|unique, current| unique.last && unique.last.path == current.path ? unique : unique + [current]}
21
+ .map(&:native_targets)
22
+ .flatten
23
+ .select {|target| !target.test_target_type?}
15
24
  end
16
25
 
17
26
  # @param [String] platform_name
@@ -36,9 +45,26 @@ module XcodeArchiveCache
36
45
  #
37
46
  def find_for_file(file)
38
47
  if file.file_ref.is_a?(Xcodeproj::Project::Object::PBXReferenceProxy)
39
- project = file.file_ref.remote_ref.container_portal_object
40
48
  product_reference_uuid = file.file_ref.remote_ref.remote_global_id_string
41
- find_with_product_ref_uuid(project, product_reference_uuid)
49
+ target = find_with_product_ref_uuid(product_reference_uuid)
50
+ if target == nil
51
+ project = file.file_ref.remote_ref.container_portal_object
52
+ target = find_in_project(project, product_reference_uuid)
53
+
54
+ # allow all targets from this project
55
+ # to be linked to that exact project
56
+ #
57
+ # otherwise, injection will operate on different Xcodeproj::Project objects
58
+ # resulting to only the last target being actually removed
59
+ #
60
+ @all_targets += extract_targets([project])
61
+ end
62
+
63
+ if target == nil
64
+ raise Informative, "Target for #{file.file_ref.path} not found"
65
+ end
66
+
67
+ target
42
68
  elsif file.file_ref.is_a?(Xcodeproj::Project::Object::PBXFileReference)
43
69
  # products of sibling project targets are added as PBXFileReferences
44
70
  targets = find_with_product_path(file.file_ref.path)
@@ -54,7 +80,7 @@ module XcodeArchiveCache
54
80
  #
55
81
  def find_for_product_name(product_name)
56
82
  all_targets.select {|native_target| native_target.name == product_name || native_target.product_reference.display_name == product_name}
57
- .first
83
+ .first
58
84
  end
59
85
 
60
86
  private
@@ -85,7 +111,16 @@ module XcodeArchiveCache
85
111
  #
86
112
  # @return [Xcodeproj::Project::Object::PBXNativeTarget]
87
113
  #
88
- def find_with_product_ref_uuid(project, uuid)
114
+ def find_with_product_ref_uuid(uuid)
115
+ all_targets.select {|target| target.product_reference.uuid == uuid}.first
116
+ end
117
+
118
+ # @param [Xcodeproj::Project] project
119
+ # @param [String] uuid
120
+ #
121
+ # @return [Xcodeproj::Project::Object::PBXNativeTarget]
122
+ #
123
+ def find_in_project(project, uuid)
89
124
  project.native_targets.select {|target| target.product_reference.uuid == uuid}.first
90
125
  end
91
126
 
@@ -34,6 +34,10 @@ module XcodeArchiveCache
34
34
  #
35
35
  attr_accessor :build_settings
36
36
 
37
+ # @return [Array<Xcodeproj::Project::Object::PBXNativeTarget>]
38
+ #
39
+ attr_reader :targets_injected_to
40
+
37
41
  # @param [String] name
38
42
  # @param [Xcodeproj::Project::Object::PBXNativeTarget] native_target
39
43
  # @param [Boolean] is_root
@@ -44,6 +48,7 @@ module XcodeArchiveCache
44
48
  @is_root = is_root
45
49
  @dependent = []
46
50
  @dependencies = []
51
+ @targets_injected_to = []
47
52
  @state = :unknown
48
53
  end
49
54
 
@@ -86,9 +91,52 @@ module XcodeArchiveCache
86
91
  # @return [String]
87
92
  #
88
93
  def dsym_file_name
89
- return nil unless build_settings
94
+ build_settings ? build_settings[XcodeArchiveCache::BuildSettings::DWARF_DSYM_FILE_NAME_KEY] : nil
95
+ end
96
+
97
+ # @return [String]
98
+ #
99
+ def original_modulemap_file_path
100
+ modulemap_file = modulemap_file_name
101
+ return unless modulemap_file
102
+
103
+ Pathname.new(modulemap_file).absolute? ? modulemap_file : File.join(File.dirname(native_target.project.path), modulemap_file)
104
+ end
105
+
106
+ # @return [String]
107
+ #
108
+ def resulting_modulemap_file_name
109
+ if module_name
110
+ module_name + ".modulemap"
111
+ else
112
+ File.basename(modulemap_file_name)
113
+ end
114
+ end
90
115
 
91
- build_settings[XcodeArchiveCache::BuildSettings::DWARF_DSYM_FILE_NAME_KEY]
116
+ # @return [String]
117
+ #
118
+ def swift_objc_interface_header_file
119
+ header_file = build_settings[XcodeArchiveCache::BuildSettings::SWIFT_OBJC_INTERFACE_HEADER_NAME_KEY]
120
+ if header_file == nil
121
+ our_module_name = module_name
122
+ return if our_module_name == nil
123
+
124
+ header_file = our_module_name + "-Swift.h"
125
+ end
126
+
127
+ header_file
128
+ end
129
+
130
+ # @return [String]
131
+ #
132
+ def module_name
133
+ build_settings[XcodeArchiveCache::BuildSettings::PRODUCT_MODULE_NAME_KEY]
134
+ end
135
+
136
+ # @return [String]
137
+ #
138
+ def modulemap_file_name
139
+ build_settings[XcodeArchiveCache::BuildSettings::MODULEMAP_FILE_KEY]
92
140
  end
93
141
 
94
142
  # @return [Array<Node>]
@@ -8,24 +8,50 @@ module XcodeArchiveCache
8
8
  @cache_storage = cache_storage
9
9
  end
10
10
 
11
+ # @param [XcodeArchiveCache::BuildGraph::Graph] graph
12
+ #
13
+ def evaluate_build_graph(graph)
14
+ return if graph.root_node.state != :unknown
15
+
16
+ # DFS over graph, evaluating dependencies first
17
+ #
18
+ stack = [graph.root_node]
19
+
20
+ while stack.length > 0
21
+ last_node = stack.last
22
+
23
+ if last_node.state == :evaluating_dependencies
24
+ # dependencies were evaluated, we're good to go
25
+ evaluate(last_node)
26
+ stack.delete_at(stack.length - 1)
27
+ elsif last_node.state == :unknown
28
+ last_node.state = :evaluating_dependencies
29
+ stack += last_node.dependencies.select { |dependency| dependency.state == :unknown }
30
+ else
31
+ stack.delete_at(stack.length - 1)
32
+ end
33
+ end
34
+ end
35
+
36
+ private
37
+
11
38
  # @param [XcodeArchiveCache::BuildGraph::Node] node
12
39
  #
13
40
  def evaluate(node)
14
- return if node.state != :unknown
41
+ has_dependencies_waiting_for_rebuild = node.dependencies
42
+ .reduce(false) { |rebuild, dependency| rebuild || dependency.waiting_for_rebuild }
15
43
 
16
44
  # we include dependency shas in every node sha calculation,
17
45
  # so if some dependency changes, that change propagates
18
46
  # all the way to the top level
19
47
  #
20
- if cache_storage.cached_artifact_path(node) == nil
48
+ if has_dependencies_waiting_for_rebuild || cache_storage.cached_artifact_path(node) == nil
21
49
  node.state = :waiting_for_rebuild
22
50
  else
23
51
  node.state = :exists_in_cache
24
52
  end
25
53
  end
26
54
 
27
- private
28
-
29
55
  # @return [XcodeArchiveCache::ArtifactCache::AbstractStorage]
30
56
  #
31
57
  attr_reader :cache_storage
@@ -2,6 +2,10 @@ module XcodeArchiveCache
2
2
  module BuildGraph
3
3
  class NodeShaCalculator
4
4
 
5
+ def initialize
6
+ @own_sha = calculate_own_sources_sha
7
+ end
8
+
5
9
  # @param [XcodeArchiveCache::BuildGraph::Node] node
6
10
  #
7
11
  def calculate(node)
@@ -24,6 +28,20 @@ module XcodeArchiveCache
24
28
 
25
29
  private
26
30
 
31
+ # @return [String]
32
+ #
33
+ attr_reader :own_sha
34
+
35
+ # @return [String]
36
+ #
37
+ def calculate_own_sources_sha
38
+ root = Pathname.new(File.expand_path('../', File.dirname(__FILE__)))
39
+ source_file_glob = File.join(root.realpath.to_s, "**", "*.rb")
40
+ source_file_paths = Dir.glob(source_file_glob)
41
+
42
+ calculate_sha(source_file_paths)
43
+ end
44
+
27
45
  # @param [XcodeArchiveCache::BuildGraph::Node] node
28
46
  #
29
47
  # @return [Array<String>]
@@ -36,6 +54,9 @@ module XcodeArchiveCache
36
54
  inputs << list_build_phase_inputs(build_phase)
37
55
  end
38
56
 
57
+ modulemap_file_path = node.original_modulemap_file_path
58
+ inputs << modulemap_file_path if modulemap_file_path
59
+
39
60
  # file path order should not affect evaluation result
40
61
  inputs.flatten.compact.sort
41
62
  end
@@ -71,7 +92,7 @@ module XcodeArchiveCache
71
92
  # @param [Array<String>] dependency_shas
72
93
  #
73
94
  def save_auxiliary_data(build_settings, dependency_shas, tempfile)
74
- file_contents = build_settings + dependency_shas.join("\n")
95
+ file_contents = build_settings + dependency_shas.join("\n") + "\nXCODE-ARCHIVE-CACHE: #{own_sha}\n"
75
96
  tempfile << file_contents
76
97
  tempfile.flush
77
98
  end