xcodeproj 1.19.0 → 1.20.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72f6eb6645b557dea09ae4be0fd400e48b0d4f1e42c31b7b61af87fd3c31a9cd
4
- data.tar.gz: 0c0bcfa7abc28721f61f48e295198da53576e90d62161c50a6cc7333c1e94455
3
+ metadata.gz: 156c030adda9cf98bf0f8b3616a1959e95f9bc1fa07227895c719aafd4d13734
4
+ data.tar.gz: 45a532a148d764028d5a58c0859ca1c5b13838cc68497b44611e79d6a65a6ccf
5
5
  SHA512:
6
- metadata.gz: 4f856d8cbee5b9b7b6bcbe7acce4034e8277fd05ac7caf0d2c317f75d622bb5c518dd2ddee67dac1c6a7fb2773aebb5a5de2cf2232af3fffc2353323fd08623d
7
- data.tar.gz: 9cf088a34dea380b56716f005c35fc601d9b193a0a4908556d4f8ccc80408ee328755ccb767dc0ed50adc0bc3e822cc9bcdcdeac405c97fc514f6dd429f746ac
6
+ metadata.gz: b7a4da4a5adb9eaa2b129758b0f432b4b6317ef8036df36275edd02d43ff80c9d0d126b012992633acab0721c91c7b7da601dcf76175e459fb07e59a772e7393
7
+ data.tar.gz: fd8d1a9c5f246264266a02b8d68a507ebf74e2b82881b4a52da754f77c5450ce322e6def0484f289c04690b449fcf09a8e3f46ce74c8e525cabe6796e868a2b1
data/README.md CHANGED
@@ -10,7 +10,7 @@ support for Xcode workspaces (`.xcworkspace`), configuration files (`.xcconfig`)
10
10
  Xcode Scheme files (`.xcscheme`).
11
11
 
12
12
  It is used in [CocoaPods](https://github.com/CocoaPods/CocoaPods) to create a
13
- a collection of supplemental libraries or frameworks, for all platforms Xcode supports.
13
+ collection of supplemental libraries or frameworks, for all platforms Xcode supports.
14
14
 
15
15
  The API reference can be found [here](http://www.rubydoc.info/gems/xcodeproj).
16
16
 
@@ -9,22 +9,33 @@ module Xcodeproj
9
9
 
10
10
  self.summary = 'Sorts the given project.'
11
11
 
12
+ def self.options
13
+ [
14
+ ['--group-option=[above|below]', 'The position of the groups when sorting. If no option is specified, sorting will interleave groups and files.'],
15
+ ].concat(super)
16
+ end
17
+
12
18
  self.arguments = [
13
19
  CLAide::Argument.new('PROJECT', false),
14
20
  ]
15
21
 
16
22
  def initialize(argv)
17
23
  self.xcodeproj_path = argv.shift_argument
24
+ @group_option = argv.option('group-option')
25
+ @group_option &&= @group_option.to_sym
18
26
  super
19
27
  end
20
28
 
21
29
  def validate!
22
30
  super
31
+ unless [nil, :above, :below].include?(@group_option)
32
+ help! "Unknown format `#{@group_option}`"
33
+ end
23
34
  open_project!
24
35
  end
25
36
 
26
37
  def run
27
- xcodeproj.sort
38
+ xcodeproj.sort(:groups_position => @group_option)
28
39
  xcodeproj.save
29
40
  puts "The `#{File.basename(xcodeproj_path)}` project was sorted"
30
41
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'shellwords'
2
3
  require 'xcodeproj/config/other_linker_flags_parser'
3
4
 
@@ -58,7 +59,7 @@ module Xcodeproj
58
59
  @attributes = {}
59
60
  @includes = []
60
61
  @other_linker_flags = {}
61
- [:simple, :frameworks, :weak_frameworks, :libraries, :force_load].each do |key|
62
+ [:simple, :frameworks, :weak_frameworks, :libraries, :arg_files, :force_load].each do |key|
62
63
  @other_linker_flags[key] = Set.new
63
64
  end
64
65
  merge!(extract_hash(xcconfig_hash_or_file))
@@ -125,9 +126,10 @@ module Xcodeproj
125
126
  :frameworks => '-framework ',
126
127
  :weak_frameworks => '-weak_framework ',
127
128
  :libraries => '-l',
129
+ :arg_files => '@',
128
130
  :force_load => '-force_load',
129
131
  }
130
- [:libraries, :frameworks, :weak_frameworks, :force_load].each do |key|
132
+ [:libraries, :frameworks, :weak_frameworks, :arg_files, :force_load].each do |key|
131
133
  modifier = modifiers[key]
132
134
  sorted = other_linker_flags[key].to_a.sort
133
135
  if key == :force_load
@@ -180,6 +182,13 @@ module Xcodeproj
180
182
  other_linker_flags[:libraries]
181
183
  end
182
184
 
185
+ # @return [Set<String>] The list of the arg files required by this
186
+ # settings file.
187
+ #
188
+ def arg_files
189
+ other_linker_flags[:arg_files]
190
+ end
191
+
183
192
  public
184
193
 
185
194
  # @!group Merging
@@ -254,6 +263,7 @@ module Xcodeproj
254
263
  # @return [Hash]
255
264
  #
256
265
  def extract_hash(argument)
266
+ return argument if argument.is_a?(Hash)
257
267
  if argument.respond_to? :read
258
268
  @filepath = Pathname.new(argument.to_path)
259
269
  hash_from_file_content(argument.read)
@@ -16,6 +16,7 @@ module Xcodeproj
16
16
  :frameworks => [],
17
17
  :weak_frameworks => [],
18
18
  :libraries => [],
19
+ :arg_files => [],
19
20
  :simple => [],
20
21
  :force_load => [],
21
22
  }
@@ -32,6 +33,8 @@ module Xcodeproj
32
33
  key = :weak_frameworks
33
34
  when '-l'
34
35
  key = :libraries
36
+ when '@'
37
+ key = :arg_files
35
38
  when '-force_load'
36
39
  key = :force_load
37
40
  else
@@ -58,6 +61,8 @@ module Xcodeproj
58
61
  flags.strip.shellsplit.flat_map do |string|
59
62
  if string =~ /\A-l.+/
60
63
  ['-l', string[2..-1]]
64
+ elsif string =~ /\A@.+/
65
+ ['@', string[1..-1]]
61
66
  else
62
67
  string
63
68
  end
@@ -32,15 +32,15 @@ module Xcodeproj
32
32
 
33
33
  # @return [String] The last known object version to Xcodeproj.
34
34
  #
35
- LAST_KNOWN_OBJECT_VERSION = 54
35
+ LAST_KNOWN_OBJECT_VERSION = 55
36
36
 
37
- # @return [String] The last known object version to Xcodeproj.
37
+ # @return [String] The last known Xcode version to Xcodeproj.
38
38
  #
39
- LAST_UPGRADE_CHECK = '1100'
39
+ LAST_UPGRADE_CHECK = '1240'
40
40
 
41
- # @return [String] The last known object version to Xcodeproj.
41
+ # @return [String] The last known Xcode version to Xcodeproj.
42
42
  #
43
- LAST_SWIFT_UPGRADE_CHECK = '1100'
43
+ LAST_SWIFT_UPGRADE_CHECK = '1240'
44
44
 
45
45
  # @return [String] The version of `.xcscheme` files supported by Xcodeproj
46
46
  #
@@ -128,6 +128,7 @@ module Xcodeproj
128
128
  # @return [Hash] The compatibility version string for different object versions.
129
129
  #
130
130
  COMPATIBILITY_VERSION_BY_OBJECT_VERSION = {
131
+ 55 => 'Xcode 13.0',
131
132
  54 => 'Xcode 12.0',
132
133
  53 => 'Xcode 11.4',
133
134
  52 => 'Xcode 11.0',
@@ -453,5 +454,12 @@ module Xcodeproj
453
454
  $(inherited)
454
455
  ${inherited}
455
456
  ).freeze
457
+
458
+ # @return [Hash] Possible types for a scheme's 'ExecutionAction' node
459
+ #
460
+ EXECUTION_ACTION_TYPE = {
461
+ :shell_script => 'Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction',
462
+ :send_email => 'Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.SendEmailAction',
463
+ }.freeze
456
464
  end
457
465
  end
@@ -1,5 +1,5 @@
1
1
  module Xcodeproj
2
2
  # The version of the xcodeproj gem.
3
3
  #
4
- VERSION = '1.19.0'.freeze unless defined? Xcodeproj::VERSION
4
+ VERSION = '1.20.0'.freeze unless defined? Xcodeproj::VERSION
5
5
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'atomos'
2
3
  require 'fileutils'
3
4
  require 'securerandom'
@@ -220,11 +221,11 @@ module Xcodeproj
220
221
  end
221
222
 
222
223
  if archive_version.to_i > Constants::LAST_KNOWN_ARCHIVE_VERSION
223
- raise '[Xcodeproj] Unknown archive version.'
224
+ raise "[Xcodeproj] Unknown archive version (#{archive_version.to_i})."
224
225
  end
225
226
 
226
227
  if object_version.to_i > Constants::LAST_KNOWN_OBJECT_VERSION
227
- raise '[Xcodeproj] Unknown object version.'
228
+ raise "[Xcodeproj] Unknown object version (#{object_version.to_i})."
228
229
  end
229
230
 
230
231
  # Projects can have product_ref_groups that are not listed in the main_groups["Products"]
@@ -711,9 +712,10 @@ module Xcodeproj
711
712
  #
712
713
  # @return [PBXNativeTarget] the target.
713
714
  #
714
- def new_target(type, name, platform, deployment_target = nil, product_group = nil, language = nil)
715
+ def new_target(type, name, platform, deployment_target = nil, product_group = nil, language = nil, product_basename = nil)
715
716
  product_group ||= products_group
716
- ProjectHelper.new_target(self, type, name, platform, deployment_target, product_group, language)
717
+ product_basename ||= name
718
+ ProjectHelper.new_target(self, type, name, platform, deployment_target, product_group, language, product_basename)
717
719
  end
718
720
 
719
721
  # Creates a new resource bundles target and adds it to the project.
@@ -731,9 +733,10 @@ module Xcodeproj
731
733
  #
732
734
  # @return [PBXNativeTarget] the target.
733
735
  #
734
- def new_resources_bundle(name, platform, product_group = nil)
736
+ def new_resources_bundle(name, platform, product_group = nil, product_basename = nil)
735
737
  product_group ||= products_group
736
- ProjectHelper.new_resources_bundle(self, name, platform, product_group)
738
+ product_basename ||= name
739
+ ProjectHelper.new_resources_bundle(self, name, platform, product_group, product_basename)
737
740
  end
738
741
 
739
742
  # Creates a new target and adds it to the project.
@@ -49,7 +49,9 @@ module Xcodeproj
49
49
  # user.
50
50
  #
51
51
  def display_name
52
- if file_ref
52
+ if product_ref
53
+ product_ref.display_name
54
+ elsif file_ref
53
55
  file_ref.display_name
54
56
  else
55
57
  super
@@ -226,24 +226,24 @@ module Xcodeproj
226
226
  # Creates a file reference to a static library and adds it to the
227
227
  # group.
228
228
  #
229
- # @param [#to_s] product_name
229
+ # @param [#to_s] product_basename
230
230
  # The name of the static library.
231
231
  #
232
232
  # @return [PBXFileReference] The new file reference.
233
233
  #
234
- def new_product_ref_for_target(target_name, product_type)
235
- FileReferencesFactory.new_product_ref_for_target(self, target_name, product_type)
234
+ def new_product_ref_for_target(product_basename, product_type)
235
+ FileReferencesFactory.new_product_ref_for_target(self, product_basename, product_type)
236
236
  end
237
237
 
238
238
  # Creates a file reference to a new bundle.
239
239
  #
240
- # @param [#to_s] product_name
240
+ # @param [#to_s] product_basename
241
241
  # The name of the bundle.
242
242
  #
243
243
  # @return [PBXFileReference] The new file reference.
244
244
  #
245
- def new_bundle(product_name)
246
- FileReferencesFactory.new_bundle(self, product_name)
245
+ def new_bundle(product_basename)
246
+ FileReferencesFactory.new_bundle(self, product_basename)
247
247
  end
248
248
 
249
249
  # Creates a file reference to a new bundle and adds it to the group.
@@ -42,17 +42,17 @@ module Xcodeproj
42
42
  # @param [PBXGroup] group
43
43
  # The group to which to add the reference.
44
44
  #
45
- # @param [#to_s] product_name
45
+ # @param [#to_s] product_basename
46
46
  # The name of the static library.
47
47
  #
48
48
  # @return [PBXFileReference] The new file reference.
49
49
  #
50
- def new_product_ref_for_target(group, target_name, product_type)
50
+ def new_product_ref_for_target(group, product_basename, product_type)
51
51
  if product_type == :static_library
52
52
  prefix = 'lib'
53
53
  end
54
54
  extension = Constants::PRODUCT_UTI_EXTENSIONS[product_type]
55
- path = "#{prefix}#{target_name}"
55
+ path = "#{prefix}#{product_basename}"
56
56
  path += ".#{extension}" if extension
57
57
  ref = new_reference(group, path, :built_products)
58
58
  ref.include_in_index = '0'
@@ -66,13 +66,13 @@ module Xcodeproj
66
66
  # @param [PBXGroup] group
67
67
  # The group to which to add the reference.
68
68
  #
69
- # @param [#to_s] product_name
69
+ # @param [#to_s] product_basename
70
70
  # The name of the bundle.
71
71
  #
72
72
  # @return [PBXFileReference] The new file reference.
73
73
  #
74
- def new_bundle(group, product_name)
75
- ref = new_reference(group, "#{product_name}.bundle", :built_products)
74
+ def new_bundle(group, product_basename)
75
+ ref = new_reference(group, "#{product_basename}.bundle", :built_products)
76
76
  ref.include_in_index = '0'
77
77
  ref.set_explicit_file_type('wrapper.cfbundle')
78
78
  ref
@@ -205,7 +205,7 @@ module Xcodeproj
205
205
  # @return [void]
206
206
  #
207
207
  def set_path_with_source_tree(object, path, source_tree)
208
- path = Pathname.new(path)
208
+ path = Pathname(path)
209
209
  source_tree = normalize_source_tree(source_tree)
210
210
  object.source_tree = source_tree
211
211
 
@@ -13,6 +13,16 @@ module Xcodeproj
13
13
  # @return [String] the product name of this Swift package.
14
14
  #
15
15
  attribute :product_name, String
16
+
17
+ # @!group AbstractObject Hooks
18
+ #--------------------------------------#
19
+
20
+ # @return [String] the name of the Swift package.
21
+ #
22
+ def display_name
23
+ return product_name if product_name
24
+ super
25
+ end
16
26
  end
17
27
  end
18
28
  end
@@ -13,6 +13,20 @@ module Xcodeproj
13
13
  # @return [Hash] the version requirements for this Swift package.
14
14
  #
15
15
  attribute :requirement, Hash
16
+
17
+ # @!group AbstractObject Hooks
18
+ #--------------------------------------#
19
+
20
+ def ascii_plist_annotation
21
+ " #{isa} \"#{File.basename(display_name)}\" "
22
+ end
23
+
24
+ # @return [String] the name of the Swift package repository.
25
+ #
26
+ def display_name
27
+ return repositoryURL if repositoryURL
28
+ super
29
+ end
16
30
  end
17
31
  end
18
32
  end
@@ -41,17 +41,17 @@ module Xcodeproj
41
41
  #
42
42
  # @return [PBXNativeTarget] the target.
43
43
  #
44
- def self.new_target(project, type, name, platform, deployment_target, product_group, language)
44
+ def self.new_target(project, type, name, platform, deployment_target, product_group, language, product_basename)
45
45
  # Target
46
46
  target = project.new(PBXNativeTarget)
47
47
  project.targets << target
48
48
  target.name = name
49
- target.product_name = name
49
+ target.product_name = product_basename
50
50
  target.product_type = Constants::PRODUCT_TYPE_UTI[type]
51
51
  target.build_configuration_list = configuration_list(project, platform, deployment_target, type, language)
52
52
 
53
53
  # Product
54
- product = product_group.new_product_ref_for_target(name, type)
54
+ product = product_group.new_product_ref_for_target(target.product_name, type)
55
55
  target.product_reference = product
56
56
 
57
57
  # Build phases
@@ -88,12 +88,12 @@ module Xcodeproj
88
88
  #
89
89
  # @return [PBXNativeTarget] the target.
90
90
  #
91
- def self.new_resources_bundle(project, name, platform, product_group)
91
+ def self.new_resources_bundle(project, name, platform, product_group, product_basename)
92
92
  # Target
93
93
  target = project.new(PBXNativeTarget)
94
94
  project.targets << target
95
95
  target.name = name
96
- target.product_name = name
96
+ target.product_name = product_basename
97
97
  target.product_type = Constants::PRODUCT_TYPE_UTI[:bundle]
98
98
 
99
99
  # Configuration List
@@ -111,7 +111,7 @@ module Xcodeproj
111
111
  target.build_configuration_list = cl
112
112
 
113
113
  # Product
114
- product = product_group.new_bundle(name)
114
+ product = product_group.new_bundle(target.product_name)
115
115
  target.product_reference = product
116
116
 
117
117
  # Build phases
@@ -9,8 +9,12 @@ require 'xcodeproj/scheme/archive_action'
9
9
 
10
10
  require 'xcodeproj/scheme/buildable_product_runnable'
11
11
  require 'xcodeproj/scheme/buildable_reference'
12
+ require 'xcodeproj/scheme/location_scenario_reference'
13
+ require 'xcodeproj/scheme/execution_action'
12
14
  require 'xcodeproj/scheme/macro_expansion'
13
15
  require 'xcodeproj/scheme/remote_runnable'
16
+ require 'xcodeproj/scheme/send_email_action_content'
17
+ require 'xcodeproj/scheme/shell_script_action_content'
14
18
 
15
19
  module Xcodeproj
16
20
  # This class represents a Scheme document represented by a ".xcscheme" file
@@ -221,7 +225,7 @@ module Xcodeproj
221
225
  launch_runnable = BuildableProductRunnable.new(build_target, 0)
222
226
  launch_action.buildable_product_runnable = launch_runnable
223
227
 
224
- profile_runnable = BuildableProductRunnable.new(build_target)
228
+ profile_runnable = BuildableProductRunnable.new(build_target, 0)
225
229
  profile_action.buildable_product_runnable = profile_runnable
226
230
 
227
231
  macro_exp = MacroExpansion.new(build_target)
@@ -23,6 +23,78 @@ module Xcodeproj
23
23
  def build_configuration=(config_name)
24
24
  @xml_element.attributes['buildConfiguration'] = config_name
25
25
  end
26
+
27
+ # @return [Array<ExecutionAction>]
28
+ # The list of actions to run before this scheme action.
29
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
30
+ #
31
+ def pre_actions
32
+ pre_actions = @xml_element.elements['PreActions']
33
+ return nil unless pre_actions
34
+ pre_actions.get_elements('ExecutionAction').map do |entry_node|
35
+ ExecutionAction.new(entry_node)
36
+ end
37
+ end
38
+
39
+ # @param [Array<ExecutionAction>] pre_actions
40
+ # Set the list of actions to run before this scheme action.
41
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
42
+ #
43
+ def pre_actions=(pre_actions)
44
+ @xml_element.delete_element('PreActions')
45
+ unless pre_actions.empty?
46
+ pre_actions_element = @xml_element.add_element('PreActions')
47
+ pre_actions.each do |entry_node|
48
+ pre_actions_element.add_element(entry_node.xml_element)
49
+ end
50
+ end
51
+ pre_actions
52
+ end
53
+
54
+ # @param [ExecutionAction] pre_action
55
+ # Add an action to the list of actions to run before this scheme action.
56
+ # It can be either a 'Run Script' or a 'Send Email' action.
57
+ #
58
+ def add_pre_action(pre_action)
59
+ pre_actions = @xml_element.elements['PreActions'] || @xml_element.add_element('PreActions')
60
+ pre_actions.add_element(pre_action.xml_element)
61
+ end
62
+
63
+ # @return [Array<ExecutionAction>]
64
+ # The list of actions to run after this scheme action.
65
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
66
+ #
67
+ def post_actions
68
+ post_actions = @xml_element.elements['PostActions']
69
+ return nil unless post_actions
70
+ post_actions.get_elements('ExecutionAction').map do |entry_node|
71
+ ExecutionAction.new(entry_node)
72
+ end
73
+ end
74
+
75
+ # @param [Array<ExecutionAction>] post_actions
76
+ # Set the list of actions to run after this scheme action.
77
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
78
+ #
79
+ def post_actions=(post_actions)
80
+ @xml_element.delete_element('PostActions')
81
+ unless post_actions.empty?
82
+ post_actions_element = @xml_element.add_element('PostActions')
83
+ post_actions.each do |entry_node|
84
+ post_actions_element.add_element(entry_node.xml_element)
85
+ end
86
+ end
87
+ post_actions
88
+ end
89
+
90
+ # @param [ExecutionAction] post_action
91
+ # Add an action to the list of actions to run after this scheme action.
92
+ # It can be either a 'Run Script' or a 'Send Email' action.
93
+ #
94
+ def add_post_action(post_action)
95
+ post_actions = @xml_element.elements['PostActions'] || @xml_element.add_element('PostActions')
96
+ post_actions.add_element(post_action.xml_element)
97
+ end
26
98
  end
27
99
  end
28
100
  end
@@ -19,6 +19,20 @@ module Xcodeproj
19
19
  end
20
20
  end
21
21
 
22
+ # @return [Bool]
23
+ # Whether or not to run post actions on build failure
24
+ #
25
+ def run_post_actions_on_failure?
26
+ string_to_bool(@xml_element.attributes['runPostActionsOnFailure'])
27
+ end
28
+
29
+ # @param [Bool] flag
30
+ # Set whether or not to run post actions on build failure
31
+ #
32
+ def run_post_actions_on_failure=(flag)
33
+ @xml_element.attributes['runPostActionsOnFailure'] = bool_to_string(flag)
34
+ end
35
+
22
36
  # @return [Bool]
23
37
  # Whether or not to build the various targets in parallel
24
38
  #
@@ -47,6 +61,78 @@ module Xcodeproj
47
61
  @xml_element.attributes['buildImplicitDependencies'] = bool_to_string(flag)
48
62
  end
49
63
 
64
+ # @return [Array<ExecutionAction>]
65
+ # The list of actions to run before this scheme action.
66
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
67
+ #
68
+ def pre_actions
69
+ pre_actions = @xml_element.elements['PreActions']
70
+ return nil unless pre_actions
71
+ pre_actions.get_elements('ExecutionAction').map do |entry_node|
72
+ ExecutionAction.new(entry_node)
73
+ end
74
+ end
75
+
76
+ # @param [Array<ExecutionAction>] pre_actions
77
+ # Set the list of actions to run before this scheme action.
78
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
79
+ #
80
+ def pre_actions=(pre_actions)
81
+ @xml_element.delete_element('PreActions')
82
+ unless pre_actions.empty?
83
+ pre_actions_element = @xml_element.add_element('PreActions')
84
+ pre_actions.each do |entry_node|
85
+ pre_actions_element.add_element(entry_node.xml_element)
86
+ end
87
+ end
88
+ pre_actions
89
+ end
90
+
91
+ # @param [ExecutionAction] pre_action
92
+ # Add an action to the list of actions to run before this scheme action.
93
+ # It can be either a 'Run Script' or a 'Send Email' action.
94
+ #
95
+ def add_pre_action(pre_action)
96
+ pre_actions = @xml_element.elements['PreActions'] || @xml_element.add_element('PreActions')
97
+ pre_actions.add_element(pre_action.xml_element)
98
+ end
99
+
100
+ # @return [Array<ExecutionAction>]
101
+ # The list of actions to run after this scheme action.
102
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
103
+ #
104
+ def post_actions
105
+ post_actions = @xml_element.elements['PostActions']
106
+ return nil unless post_actions
107
+ post_actions.get_elements('ExecutionAction').map do |entry_node|
108
+ ExecutionAction.new(entry_node)
109
+ end
110
+ end
111
+
112
+ # @param [Array<ExecutionAction>] post_actions
113
+ # Set the list of actions to run after this scheme action.
114
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
115
+ #
116
+ def post_actions=(post_actions)
117
+ @xml_element.delete_element('PostActions')
118
+ unless post_actions.empty?
119
+ post_actions_element = @xml_element.add_element('PostActions')
120
+ post_actions.each do |entry_node|
121
+ post_actions_element.add_element(entry_node.xml_element)
122
+ end
123
+ end
124
+ post_actions
125
+ end
126
+
127
+ # @param [ExecutionAction] post_action
128
+ # Add an action to the list of actions to run after this scheme action.
129
+ # It can be either a 'Run Script' or a 'Send Email' action.
130
+ #
131
+ def add_post_action(post_action)
132
+ post_actions = @xml_element.elements['PostActions'] || @xml_element.add_element('PostActions')
133
+ post_actions.add_element(post_action.xml_element)
134
+ end
135
+
50
136
  # @return [Array<BuildAction::Entry>]
51
137
  # The list of BuildActionEntry nodes associated with this Build Action.
52
138
  # Each entry represent a target to build and tells for which action it's needed to be built.
@@ -103,11 +189,11 @@ module Xcodeproj
103
189
  is_app_target = app_types.include?(target_or_node.product_type)
104
190
  end
105
191
 
106
- self.build_for_analyzing = true
107
192
  self.build_for_testing = is_test_target
108
193
  self.build_for_running = is_app_target
109
194
  self.build_for_profiling = is_app_target
110
195
  self.build_for_archiving = is_app_target
196
+ self.build_for_analyzing = true
111
197
 
112
198
  add_buildable_reference BuildableReference.new(target_or_node) if target_or_node
113
199
  end
@@ -0,0 +1,86 @@
1
+ module Xcodeproj
2
+ class XCScheme
3
+ # This class wraps the ExecutionAction node of a .xcscheme XML file
4
+ #
5
+ class ExecutionAction < XMLElementWrapper
6
+ # @param [REXML::Element] node
7
+ # The 'ExecutionAction' XML node that this object will wrap.
8
+ # If nil, will create an empty one
9
+ #
10
+ # @param [Symbol] action_type
11
+ # One of `EXECUTION_ACTION_TYPE.keys`
12
+ #
13
+ def initialize(node = nil, action_type = nil)
14
+ create_xml_element_with_fallback(node, 'ExecutionAction') do
15
+ type = action_type || node.action_type
16
+ raise "[Xcodeproj] Invalid ActionType `#{type}`" unless Constants::EXECUTION_ACTION_TYPE.keys.include?(type)
17
+ @xml_element.attributes['ActionType'] = Constants::EXECUTION_ACTION_TYPE[type]
18
+ end
19
+ end
20
+
21
+ # @return [String]
22
+ # The ActionType of this ExecutionAction. One of two values:
23
+ #
24
+ # Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction,
25
+ # Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.SendEmailAction
26
+ #
27
+ def action_type
28
+ @xml_element.attributes['ActionType']
29
+ end
30
+
31
+ # @return [ShellScriptActionContent]
32
+ # If action_type is 'Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction'
33
+ # returns the contents of the shell script to run pre/post action.
34
+ #
35
+ # @return [SendEmailActionContent]
36
+ # If action_type is 'Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.SendEmailAction'
37
+ # returns the contents of the email to send pre/post action.
38
+ #
39
+ def action_content
40
+ case action_type
41
+ when Constants::EXECUTION_ACTION_TYPE[:shell_script]
42
+ ShellScriptActionContent.new(@xml_element.elements['ActionContent'])
43
+ when Constants::EXECUTION_ACTION_TYPE[:send_email]
44
+ SendEmailActionContent.new(@xml_element.elements['ActionContent'])
45
+ else
46
+ raise "[Xcodeproj] Invalid ActionType `#{action_type}`"
47
+ end
48
+ end
49
+
50
+ # @param [ShellScriptActionContent, SendEmailActionContent] value
51
+ # Set either the contents of the shell script to run pre/post action
52
+ # or the contents of the email to send pre/post action.
53
+ #
54
+ def action_content=(value)
55
+ raise "[Xcodeproj] Invalid ActionContent `#{value.class}` for " \
56
+ "ActionType `#{action_type}`" unless valid_action_content?(value)
57
+
58
+ @xml_element.delete_element('ActionContent')
59
+ @xml_element.add_element(value.xml_element)
60
+ end
61
+
62
+ #-------------------------------------------------------------------------#
63
+
64
+ private
65
+
66
+ # @!group Private helpers
67
+
68
+ # @return [Bool]
69
+ # True if value (ActionContent) is valid for current action_type
70
+ #
71
+ # @param [ShellScriptActionContent, SendEmailActionContent] value
72
+ # Checks if value matches the expected action_type if present.
73
+ #
74
+ def valid_action_content?(value)
75
+ case action_type
76
+ when Constants::EXECUTION_ACTION_TYPE[:shell_script]
77
+ value.is_a?(ShellScriptActionContent)
78
+ when Constants::EXECUTION_ACTION_TYPE[:send_email]
79
+ value.is_a?(SendEmailActionContent)
80
+ else
81
+ false
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -11,6 +11,8 @@ module Xcodeproj
11
11
  #
12
12
  def initialize(node = nil)
13
13
  create_xml_element_with_fallback(node, 'LaunchAction') do
14
+ self.build_configuration = 'Debug'
15
+
14
16
  # Add some attributes (that are not handled by this wrapper class yet but expected in the XML)
15
17
  @xml_element.attributes['selectedDebuggerIdentifier'] = 'Xcode.DebuggerFoundation.Debugger.LLDB'
16
18
  @xml_element.attributes['selectedLauncherIdentifier'] = 'Xcode.DebuggerFoundation.Launcher.LLDB'
@@ -19,10 +21,8 @@ module Xcodeproj
19
21
  @xml_element.attributes['ignoresPersistentStateOnLaunch'] = bool_to_string(false)
20
22
  @xml_element.attributes['debugDocumentVersioning'] = bool_to_string(true)
21
23
  @xml_element.attributes['debugServiceExtension'] = 'internal'
22
- @xml_element.add_element('AdditionalOptions')
23
24
 
24
25
  # Setup default values for other (handled) attributes
25
- self.build_configuration = 'Debug'
26
26
  self.allow_location_simulation = true
27
27
  end
28
28
  end
@@ -47,6 +47,21 @@ module Xcodeproj
47
47
  @xml_element.attributes['allowLocationSimulation'] = bool_to_string(flag)
48
48
  end
49
49
 
50
+ # @return [LocationScenarioReference]
51
+ # The LocationScenarioReference to simulate a GPS location when executing the Launch Action
52
+ #
53
+ def location_scenario_reference?
54
+ LocationScenarioReference.new(@xml_element.elements['LocationScenarioReference'])
55
+ end
56
+
57
+ # @return [LocationScenarioReference]
58
+ # Set the LocationScenarioReference which simulates a GPS location when executing the Launch Action
59
+ #
60
+ def location_scenario_reference=(reference)
61
+ @xml_element.delete_element('LocationScenarioReference')
62
+ @xml_element.add_element(reference.xml_element) if reference
63
+ end
64
+
50
65
  # @return [Bool]
51
66
  # Whether this Build Action should disable detection of UI API misuse
52
67
  # from background threads
@@ -0,0 +1,49 @@
1
+ module Xcodeproj
2
+ class XCScheme
3
+ # This class wraps the LocationScenarioReference node of a .xcscheme XML file
4
+ #
5
+ # A LocationScenarioReference is a reference to a simulated GPS location associated
6
+ # with a scheme's launch action
7
+ #
8
+ class LocationScenarioReference < XMLElementWrapper
9
+ # @param [Xcodeproj::Project::Object::AbstractTarget, REXML::Element] target_or_node
10
+ # Either the Xcode target to reference,
11
+ # or an existing XML 'LocationScenarioReference' node element to reference
12
+ #
13
+ def initialize(target_or_node)
14
+ create_xml_element_with_fallback(target_or_node, 'LocationScenarioReference') do
15
+ self.identifier = ''
16
+ self.reference_type = '0'
17
+ end
18
+ end
19
+
20
+ # @return [String]
21
+ # The identifier of a built-in location scenario reference, or a path to a GPX file
22
+ #
23
+ def identifier
24
+ @xml_element.attributes['identifier']
25
+ end
26
+
27
+ # @param [String] value
28
+ # Set the identifier for the location scenario reference
29
+ #
30
+ def identifier=(value)
31
+ @xml_element.attributes['identifier'] = value
32
+ end
33
+
34
+ # @return [String]
35
+ # The reference type is 0 when using a custom GPX file, or 1 when using a built-in location reference
36
+ #
37
+ def reference_type
38
+ @xml_element.attributes['referenceType']
39
+ end
40
+
41
+ # @param [String] value
42
+ # Set the reference type for the location scenario reference
43
+ #
44
+ def reference_type=(value)
45
+ @xml_element.attributes['referenceType'] = value
46
+ end
47
+ end
48
+ end
49
+ end
@@ -11,14 +11,14 @@ module Xcodeproj
11
11
  #
12
12
  def initialize(node = nil)
13
13
  create_xml_element_with_fallback(node, 'ProfileAction') do
14
+ # Setup default values for other (handled) attributes
15
+ self.build_configuration = 'Release'
16
+ self.should_use_launch_scheme_args_env = true
17
+
14
18
  # Add some attributes (that are not handled by this wrapper class yet but expected in the XML)
15
19
  @xml_element.attributes['savedToolIdentifier'] = ''
16
20
  @xml_element.attributes['useCustomWorkingDirectory'] = bool_to_string(false)
17
21
  @xml_element.attributes['debugDocumentVersioning'] = bool_to_string(true)
18
-
19
- # Setup default values for other (handled) attributes
20
- self.build_configuration = 'Release'
21
- self.should_use_launch_scheme_args_env = true
22
22
  end
23
23
  end
24
24
 
@@ -42,7 +42,7 @@ module Xcodeproj
42
42
  # The BuildableProductRunnable to launch when launching the Profile action
43
43
  #
44
44
  def buildable_product_runnable
45
- BuildableProductRunnable.new @xml_element.elements['BuildableProductRunnable']
45
+ BuildableProductRunnable.new @xml_element.elements['BuildableProductRunnable'], 0
46
46
  end
47
47
 
48
48
  # @param [BuildableProductRunnable] runnable
@@ -0,0 +1,84 @@
1
+ module Xcodeproj
2
+ class XCScheme
3
+ # This class wraps a 'ActionContent' node of type
4
+ # 'Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.SendEmailAction' of a .xcscheme XML file
5
+ #
6
+ class SendEmailActionContent < XMLElementWrapper
7
+ # @param [REXML::Element] node
8
+ # The 'ActionContent' XML node that this object will wrap.
9
+ # If nil, will create a default XML node to use.
10
+ #
11
+ def initialize(node = nil)
12
+ create_xml_element_with_fallback(node, 'ActionContent') do
13
+ self.title = 'Send Email'
14
+ # For some reason this is not visible in Xcode's UI and it's always set to 'NO'
15
+ # couldn't find much documentation on it so it might be safer to keep it read only
16
+ @xml_element.attributes['attachLogToEmail'] = 'NO'
17
+ end
18
+ end
19
+
20
+ # @return [Bool]
21
+ # Whether or not this action should attach log to email
22
+ #
23
+ def attach_log_to_email?
24
+ string_to_bool(@xml_element.attributes['attachLogToEmail'])
25
+ end
26
+
27
+ # @return [String]
28
+ # The title of this ActionContent
29
+ #
30
+ def title
31
+ @xml_element.attributes['title']
32
+ end
33
+
34
+ # @param [String] value
35
+ # Set the title of this ActionContent
36
+ #
37
+ def title=(value)
38
+ @xml_element.attributes['title'] = value
39
+ end
40
+
41
+ # @return [String]
42
+ # The email recipient of this ActionContent
43
+ #
44
+ def email_recipient
45
+ @xml_element.attributes['emailRecipient']
46
+ end
47
+
48
+ # @param [String] value
49
+ # Set the email recipient of this ActionContent
50
+ #
51
+ def email_recipient=(value)
52
+ @xml_element.attributes['emailRecipient'] = value
53
+ end
54
+
55
+ # @return [String]
56
+ # The email subject of this ActionContent
57
+ #
58
+ def email_subject
59
+ @xml_element.attributes['emailSubject']
60
+ end
61
+
62
+ # @param [String] value
63
+ # Set the email subject of this ActionContent
64
+ #
65
+ def email_subject=(value)
66
+ @xml_element.attributes['emailSubject'] = value
67
+ end
68
+
69
+ # @return [String]
70
+ # The email body of this ActionContent
71
+ #
72
+ def email_body
73
+ @xml_element.attributes['emailBody']
74
+ end
75
+
76
+ # @param [String] value
77
+ # Set the email body of this ActionContent
78
+ #
79
+ def email_body=(value)
80
+ @xml_element.attributes['emailBody'] = value
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,77 @@
1
+ module Xcodeproj
2
+ class XCScheme
3
+ # This class wraps a 'ActionContent' node of type
4
+ # 'Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction' of a .xcscheme XML file
5
+ #
6
+ class ShellScriptActionContent < XMLElementWrapper
7
+ # @param [REXML::Element] node
8
+ # The 'ActionContent' XML node that this object will wrap.
9
+ # If nil, will create a default XML node to use.
10
+ #
11
+ def initialize(node = nil)
12
+ create_xml_element_with_fallback(node, 'ActionContent') do
13
+ self.title = 'Run Script'
14
+ end
15
+ end
16
+
17
+ # @return [String]
18
+ # The title of this ActionContent
19
+ #
20
+ def title
21
+ @xml_element.attributes['title']
22
+ end
23
+
24
+ # @param [String] value
25
+ # Set the title of this ActionContent
26
+ #
27
+ def title=(value)
28
+ @xml_element.attributes['title'] = value
29
+ end
30
+
31
+ # @return [String]
32
+ # The contents of the shell script represented by this ActionContent
33
+ #
34
+ def script_text
35
+ @xml_element.attributes['scriptText']
36
+ end
37
+
38
+ # @param [String] value
39
+ # Set the contents of the shell script represented by this ActionContent
40
+ #
41
+ def script_text=(value)
42
+ @xml_element.attributes['scriptText'] = value
43
+ end
44
+
45
+ # @return [String]
46
+ # The preferred shell to invoke with this ActionContent
47
+ #
48
+ def shell_to_invoke
49
+ @xml_element.attributes['shellToInvoke']
50
+ end
51
+
52
+ # @param [String] value
53
+ # Set the preferred shell to invoke with this ActionContent
54
+ #
55
+ def shell_to_invoke=(value)
56
+ @xml_element.attributes['shellToInvoke'] = value
57
+ end
58
+
59
+ # @return [BuildableReference]
60
+ # The BuildableReference (Xcode target) associated with this ActionContent
61
+ #
62
+ def buildable_reference
63
+ BuildableReference.new(@xml_element.elements['EnvironmentBuildable'].elements['BuildableReference'])
64
+ end
65
+
66
+ # @param [BuildableReference] ref
67
+ # Set the BuildableReference (Xcode target) associated with this ActionContent
68
+ #
69
+ def buildable_reference=(ref)
70
+ @xml_element.delete_element('EnvironmentBuildable')
71
+
72
+ env_buildable = @xml_element.add_element('EnvironmentBuildable')
73
+ env_buildable.add_element(ref.xml_element)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -11,11 +11,11 @@ module Xcodeproj
11
11
  #
12
12
  def initialize(node = nil)
13
13
  create_xml_element_with_fallback(node, 'TestAction') do
14
+ self.build_configuration = 'Debug'
14
15
  @xml_element.attributes['selectedDebuggerIdentifier'] = 'Xcode.DebuggerFoundation.Debugger.LLDB'
15
16
  @xml_element.attributes['selectedLauncherIdentifier'] = 'Xcode.DebuggerFoundation.Launcher.LLDB'
16
- @xml_element.add_element('AdditionalOptions')
17
17
  self.should_use_launch_scheme_args_env = true
18
- self.build_configuration = 'Debug'
18
+ @xml_element.add_element('Testables')
19
19
  end
20
20
  end
21
21
 
@@ -109,7 +109,11 @@ module Xcodeproj
109
109
  # Add a MacroExpansion to this TestAction
110
110
  #
111
111
  def add_macro_expansion(macro_expansion)
112
- @xml_element.add_element(macro_expansion.xml_element)
112
+ if testables = @xml_element.elements['Testables']
113
+ @xml_element.insert_before(testables, macro_expansion.xml_element)
114
+ else
115
+ @xml_element.add_element(macro_expansion.xml_element)
116
+ end
113
117
  end
114
118
 
115
119
  # @return [EnvironmentVariables]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xcodeproj
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.19.0
4
+ version: 1.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eloy Duran
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-09 00:00:00.000000000 Z
11
+ date: 2021-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: atomos
@@ -92,6 +92,20 @@ dependencies:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
94
  version: 0.3.0
95
+ - !ruby/object:Gem::Dependency
96
+ name: rexml
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: 3.2.4
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: 3.2.4
95
109
  description: Xcodeproj lets you create and modify Xcode projects from Ruby. Script
96
110
  boring management tasks or build Xcode-friendly libraries. Also includes support
97
111
  for Xcode workspaces (.xcworkspace) and configuration files (.xcconfig).
@@ -152,10 +166,14 @@ files:
152
166
  - lib/xcodeproj/scheme/buildable_reference.rb
153
167
  - lib/xcodeproj/scheme/command_line_arguments.rb
154
168
  - lib/xcodeproj/scheme/environment_variables.rb
169
+ - lib/xcodeproj/scheme/execution_action.rb
155
170
  - lib/xcodeproj/scheme/launch_action.rb
171
+ - lib/xcodeproj/scheme/location_scenario_reference.rb
156
172
  - lib/xcodeproj/scheme/macro_expansion.rb
157
173
  - lib/xcodeproj/scheme/profile_action.rb
158
174
  - lib/xcodeproj/scheme/remote_runnable.rb
175
+ - lib/xcodeproj/scheme/send_email_action_content.rb
176
+ - lib/xcodeproj/scheme/shell_script_action_content.rb
159
177
  - lib/xcodeproj/scheme/test_action.rb
160
178
  - lib/xcodeproj/scheme/xml_element_wrapper.rb
161
179
  - lib/xcodeproj/user_interface.rb
@@ -183,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
183
201
  - !ruby/object:Gem::Version
184
202
  version: '0'
185
203
  requirements: []
186
- rubygems_version: 3.1.2
204
+ rubygems_version: 3.0.3
187
205
  signing_key:
188
206
  specification_version: 3
189
207
  summary: Create and modify Xcode projects from Ruby.