xcodeproj 0.10.1 → 0.11.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
  SHA1:
3
- metadata.gz: 6468f6b75aff22cc08a717290a382693e8125588
4
- data.tar.gz: 3dbb139858843463ea7fb130da5d3d06477339c4
3
+ metadata.gz: 4cf7c67e37553582eac9e119e155558e65ce2438
4
+ data.tar.gz: dd844950bbe7c28793d938ac2a9926d8721b8755
5
5
  SHA512:
6
- metadata.gz: 91a24f65192034d96f77e24d9e6eff7295c7ec25b6bcaf7914ad4ea430ac6ab0cbb236d6eeacf0eea0a4e04941f06dfe5cb33988e1e89fee1fe9004095941599
7
- data.tar.gz: b1c8ba00d8a772a4d3db04dd3d3a20ce9536a8013650397fe6301e1e3917a8c4e5b6c057f9633017c3db04ee8b68452fea69eabf79c30e12a71ec9d76c65dbe8
6
+ metadata.gz: 79704df4aaa923f2b2938e9291b3acade4b46d60e15c7919626460c697cd814d3b8916860fbfed96338998a6ca94299874aee91a46ebd096506af8acf050d13a
7
+ data.tar.gz: 2ec745a65f34fdf8a3c103fb75ecc318c0746619e9a545bf05fe6eef4c0d2b1a7bbf836f085aa9f1ec4179397cb17cb4626ed3c4d5cdc12397e2d62ea7dab4a9
@@ -256,10 +256,12 @@ write_plist(VALUE self, VALUE hash, VALUE path) {
256
256
  if (!success) {
257
257
  CFShow(errorString);
258
258
  }
259
+ CFWriteStreamClose(stream);
259
260
  } else {
260
261
  printf("Unable to open stream!\n");
261
262
  }
262
263
 
264
+ CFRelease(stream);
263
265
  CFRelease(dict);
264
266
  return success ? Qtrue : Qfalse;
265
267
  }
@@ -6,6 +6,7 @@ module Xcodeproj
6
6
  autoload :TargetDiff, 'xcodeproj/command/target_diff'
7
7
  autoload :ProjectDiff, 'xcodeproj/command/project_diff'
8
8
  autoload :Show, 'xcodeproj/command/show'
9
+ autoload :Sort, 'xcodeproj/command/sort'
9
10
 
10
11
  class Help < StandardError
11
12
  def initialize(command_class, argv, unrecognized_command = nil)
@@ -45,7 +46,7 @@ module Xcodeproj
45
46
  end
46
47
 
47
48
  def self.banner
48
- commands = ['target-diff', 'project-diff', 'show']
49
+ commands = ['target-diff', 'project-diff', 'show', 'sort']
49
50
  banner = "To see help for the available commands run:\n\n"
50
51
  banner + commands.map { |cmd| " * $ xcodeproj #{cmd.green} --help" }.join("\n")
51
52
  end
@@ -92,6 +93,7 @@ module Xcodeproj
92
93
  when 'target-diff' then TargetDiff
93
94
  when 'project-diff' then ProjectDiff
94
95
  when 'show' then Show
96
+ when 'sort' then Sort
95
97
  end
96
98
 
97
99
  if command_class.nil?
@@ -127,7 +129,7 @@ module Xcodeproj
127
129
  end
128
130
 
129
131
  def xcodeproj
130
- @xcodeproj ||= Project.new(xcodeproj_path)
132
+ @xcodeproj ||= Project.open(xcodeproj_path)
131
133
  end
132
134
  end
133
135
  end
@@ -19,7 +19,7 @@ module Xcodeproj
19
19
  def initialize(argv)
20
20
  xcodeproj_path = argv.shift_argument
21
21
  @xcodeproj_path = File.expand_path(xcodeproj_path) if xcodeproj_path
22
-
22
+
23
23
  if argv.option('--format')
24
24
  @output_format = argv.shift_argument
25
25
  end
@@ -0,0 +1,29 @@
1
+ module Xcodeproj
2
+ class Command
3
+ class Sort < Command
4
+ def self.banner
5
+ %{Sorts the give project
6
+
7
+ $ sort [PROJECT]
8
+
9
+ If no `PROJECT' is specified then the current work directory is searched
10
+ for one.}
11
+ end
12
+
13
+ def initialize(argv)
14
+ xcodeproj_path = argv.shift_argument
15
+ @xcodeproj_path = File.expand_path(xcodeproj_path) if xcodeproj_path
16
+ super unless argv.empty?
17
+ end
18
+
19
+ def run
20
+ xcodeproj.sort
21
+ xcodeproj.save
22
+ puts "The `#{File.basename(xcodeproj_path)}` project was sorted"
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+
29
+
@@ -22,7 +22,7 @@ module Xcodeproj
22
22
 
23
23
  # @return [String] The last known object version to Xcodeproj.
24
24
  #
25
- LAST_UPGRADE_CHECK = '0450'
25
+ LAST_UPGRADE_CHECK = '0500'
26
26
 
27
27
  # @return [Hash] The all the known ISAs grouped by superclass.
28
28
  #
@@ -83,6 +83,7 @@ module Xcodeproj
83
83
  'sh' => 'text.script.sh',
84
84
  'plist' => 'text.plist.xml',
85
85
  'markdown' => 'text',
86
+ 'xcassets' => 'folder.assetcatalog'
86
87
  }.freeze
87
88
 
88
89
  # @return [Hash] The uniform type identifier of various product types.
@@ -117,21 +118,17 @@ module Xcodeproj
117
118
  'GCC_SYMBOLS_PRIVATE_EXTERN' => 'NO',
118
119
  'GCC_OPTIMIZATION_LEVEL' => '0',
119
120
  'COPY_PHASE_STRIP' => 'NO',
120
- # TODO: enable after Xcode 4
121
- # 'ONLY_ACTIVE_ARCH' => 'YES',
122
121
  }.freeze,
123
122
  :release => {
124
123
  'OTHER_CFLAGS' => ['-DNS_BLOCK_ASSERTIONS=1', "$(inherited)"],
125
124
  'OTHER_CPLUSPLUSFLAGS' => ['-DNS_BLOCK_ASSERTIONS=1', "$(inherited)"],
126
125
  }.freeze,
127
126
  :ios => {
128
- 'ARCHS' => "$(ARCHS_STANDARD_32_BIT)",
129
127
  'IPHONEOS_DEPLOYMENT_TARGET' => '4.3',
130
128
  'PUBLIC_HEADERS_FOLDER_PATH' => "$(TARGET_NAME)",
131
129
  'SDKROOT' => 'iphoneos',
132
130
  }.freeze,
133
131
  :osx => {
134
- 'ARCHS' => "$(ARCHS_STANDARD_64_BIT)",
135
132
  'GCC_ENABLE_OBJC_EXCEPTIONS' => 'YES',
136
133
  'GCC_VERSION' => 'com.apple.compilers.llvm.clang.1_0',
137
134
  'MACOSX_DEPLOYMENT_TARGET' => '10.7',
@@ -139,7 +136,7 @@ module Xcodeproj
139
136
  'COMBINE_HIDPI_IMAGES' => 'YES',
140
137
  }.freeze,
141
138
  [:osx, :debug] => {
142
- 'ONLY_ACTIVE_ARCH' => 'YES',
139
+ # Empty?
143
140
  }.freeze,
144
141
  [:osx, :release] => {
145
142
  'DEBUG_INFORMATION_FORMAT' => 'dwarf-with-dsym',
@@ -158,8 +155,7 @@ module Xcodeproj
158
155
  :release => {
159
156
  }.freeze,
160
157
  :debug => {
161
- # TODO: enable after Xcode 4
162
- # 'ONLY_ACTIVE_ARCH' => 'YES',
158
+ 'ONLY_ACTIVE_ARCH' => 'YES',
163
159
  }.freeze,
164
160
  }.freeze
165
161
 
@@ -1,6 +1,6 @@
1
1
  module Xcodeproj
2
2
  # The version of the xcodeproj gem.
3
3
  #
4
- VERSION = '0.10.1' unless defined? Xcodeproj::VERSION
4
+ VERSION = '0.11.0' unless defined? Xcodeproj::VERSION
5
5
  end
6
6
 
@@ -334,11 +334,11 @@ module Xcodeproj
334
334
  File.open(filename, 'wb') { |file| file.write(output) }
335
335
  end
336
336
 
337
- #-------------------------------------------------------------------------#
338
337
 
339
338
  public
340
339
 
341
340
  # @!group Creating objects
341
+ #-------------------------------------------------------------------------#
342
342
 
343
343
  # Creates a new object with a suitable UUID.
344
344
  #
@@ -408,11 +408,11 @@ module Xcodeproj
408
408
  @available_uuids += uniques
409
409
  end
410
410
 
411
- #-------------------------------------------------------------------------#
412
411
 
413
412
  public
414
413
 
415
414
  # @!group Convenience accessors
415
+ #-------------------------------------------------------------------------#
416
416
 
417
417
  # @return [Array<AbstractObject>] all the objects of the project.
418
418
  #
@@ -491,7 +491,7 @@ module Xcodeproj
491
491
  # @return [PBXGroup] the `Frameworks` group creating it if necessary.
492
492
  #
493
493
  def frameworks_group
494
- main_group['Frameworks'] || new_group('Frameworks')
494
+ main_group['Frameworks'] || main_group.new_group('Frameworks')
495
495
  end
496
496
 
497
497
  # @return [ObjectList<XCBuildConfiguration>] A list of project wide
@@ -513,11 +513,11 @@ module Xcodeproj
513
513
  root_object.build_configuration_list.build_settings(name)
514
514
  end
515
515
 
516
- #-------------------------------------------------------------------------#
517
516
 
518
517
  public
519
518
 
520
- # @!group Helpers for generating objects
519
+ # @!group Helpers
520
+ #-------------------------------------------------------------------------#
521
521
 
522
522
  # Creates a new file reference in the main group.
523
523
  #
@@ -539,32 +539,6 @@ module Xcodeproj
539
539
  main_group.new_group(name, path, source_tree)
540
540
  end
541
541
 
542
- # Adds a file reference for a system framework to the project if needed and
543
- # adds it to the {PBXFrameworksBuildPhase} of the given target.
544
- #
545
- # @example Adding QuartzCore
546
- #
547
- # framework = project.add_system_framework('QuartzCore', :ios)
548
- #
549
- # target = project.targets.first
550
- # build_phase = target.frameworks_build_phases.first
551
- # build_phase.files << framework.buildFiles.new
552
- #
553
- # @param [String] name
554
- # The name of a framework.
555
- #
556
- # @param [PBXNativeTarget] target
557
- # The target to which to add the framework.
558
- #
559
- # @note This method adds a reference to the highest know SDK for the
560
- # given platform.
561
- #
562
- # @return [PBXFileReference] The file reference of the framework.
563
- #
564
- def add_system_framework(name, target)
565
- ProjectHelper.add_system_framework(self, name, target)
566
- end
567
-
568
542
  # Creates a new target and adds it to the project.
569
543
  #
570
544
  # The target is configured for the given platform and its file reference it
@@ -637,7 +611,20 @@ module Xcodeproj
637
611
  end
638
612
  end
639
613
 
614
+ # Sorts the project.
615
+ #
616
+ # @return [void]
617
+ #
618
+ def sort
619
+ root_object.sort_recursively
620
+ end
621
+
622
+
623
+ public
624
+
625
+ # @!group Helpers
640
626
  #-------------------------------------------------------------------------#
627
+
641
628
  # Get list of shared schemes in project
642
629
  #
643
630
  # @param [String] path
@@ -645,7 +632,7 @@ module Xcodeproj
645
632
  #
646
633
  # @return [Array]
647
634
  #
648
- def self.schemes project_path
635
+ def self.schemes(project_path)
649
636
  schemes = Dir[File.join(project_path, 'xcshareddata', 'xcschemes', '*.xcscheme')].map do |scheme|
650
637
  File.basename(scheme, '.xcscheme')
651
638
  end
@@ -131,9 +131,36 @@ module Xcodeproj
131
131
  isa.gsub(/^(PBX|XC)/, '')
132
132
  end
133
133
  end
134
-
135
134
  alias :to_s :display_name
136
135
 
136
+ # Sorts the to many attributes of the object according to the display
137
+ # name.
138
+ #
139
+ def sort
140
+ to_many_attributes.each do |attrb|
141
+ list = attrb.get_value(self)
142
+ list.sort! do |x, y|
143
+ x.display_name <=> y.display_name
144
+ end
145
+ end
146
+ end
147
+
148
+ # Sorts the object and the objects that it references.
149
+ #
150
+ def sort_recursively
151
+ to_one_attributes.each do |attrb|
152
+ value = attrb.get_value(self)
153
+ value.sort_recursively if value
154
+ end
155
+
156
+ to_many_attributes.each do |attrb|
157
+ list = attrb.get_value(self)
158
+ list.each(&:sort_recursively)
159
+ end
160
+
161
+ sort
162
+ end
163
+
137
164
  # @!group Reference counting
138
165
 
139
166
  # @return [Array<ObjectList>] The list of the objects that have a
@@ -23,11 +23,11 @@ module Xcodeproj
23
23
  #
24
24
  has_one :base_configuration_reference, PBXFileReference
25
25
 
26
- #---------------------------------------------------------------------#
27
26
 
28
27
  public
29
28
 
30
29
  # @!group AbstractObject Hooks
30
+ #---------------------------------------------------------------------#
31
31
 
32
32
  # @return [Hash{String => Hash}] A hash suitable to display the object
33
33
  # to the user.
@@ -41,6 +41,25 @@ module Xcodeproj
41
41
  { name => data }
42
42
  end
43
43
 
44
+
45
+ public
46
+
47
+ # @!group Helpers
48
+ # --------------------------------------------------------------------#
49
+
50
+ # Sorts the build settings. Valid only in Ruby > 1.9.2 because in
51
+ # previous versions the hash are not sorted.
52
+ #
53
+ # @return [void]
54
+ #
55
+ def sort
56
+ sorted = {}
57
+ build_settings.keys.sort.each do |key|
58
+ sorted[key] = build_settings[key]
59
+ end
60
+ self.build_settings = sorted
61
+ end
62
+
44
63
  #---------------------------------------------------------------------#
45
64
 
46
65
  end
@@ -48,37 +48,62 @@ module Xcodeproj
48
48
  # referenced by this build phase.
49
49
  #
50
50
  def files_references
51
- files.map { |bf| bf.file_ref }.uniq
51
+ files.map { |bf| bf.file_ref }
52
+ end
53
+
54
+ # @return [Array<String>] The display name of the build files.
55
+ #
56
+ def file_display_names
57
+ files.map(&:display_name)
58
+ end
59
+
60
+ # @return [PBXBuildFile] the first build file associated with the given
61
+ # file reference if one exists.
62
+ #
63
+ def build_file(file_ref)
64
+ (file_ref.referrers & files).first
65
+ end
66
+
67
+ # Returns whether a build file for the given file reference exists.
68
+ #
69
+ # @param [PBXFileReference] file_ref
70
+ #
71
+ # @return [Bool] whether the reference is already present.
72
+ #
73
+ def include?(file_ref)
74
+ !build_file(file_ref).nil?
52
75
  end
53
76
 
54
77
  # Adds a new build file, initialized with the given file reference, to
55
78
  # the phase.
56
79
  #
57
- # @param [PBXFileReference] file
58
- # the file reference that should be added to the build phase.
80
+ # @param [PBXFileReference] file_ref
81
+ # The file reference that should be added to the build phase.
59
82
  #
60
83
  # @return [PBXBuildFile] the build file generated.
61
84
  #
62
- def add_file_reference(file)
63
- build_file = project.new(PBXBuildFile)
64
- build_file.file_ref = file
65
- files << build_file
66
- build_file
85
+ def add_file_reference(file_ref, avoid_duplicates = false)
86
+ if avoid_duplicates && existing = build_file(file_ref)
87
+ existing
88
+ else
89
+ build_file = project.new(PBXBuildFile)
90
+ build_file.file_ref = file_ref
91
+ files << build_file
92
+ build_file
93
+ end
67
94
  end
68
95
 
69
96
  # Removes the build file associated with the given file reference from
70
97
  # the phase.
71
98
  #
72
- # @param [PBXFileReference] file the file to remove
99
+ # @param [PBXFileReference] file_ref
100
+ # The file to remove
73
101
  #
74
102
  # @return [void]
75
103
  #
76
- def remove_file_reference(file)
77
- build_file = files.find { |bf| bf.file_ref == file }
78
- if build_file
79
- build_file.file_ref = nil
80
- build_file.remove_from_project
81
- end
104
+ def remove_file_reference(file_ref)
105
+ build_file = files.find { |bf| bf.file_ref == file_ref }
106
+ remove_build_file(build_file) if build_file
82
107
  end
83
108
 
84
109
  # Removes a build file from the phase and clears its relationship to
@@ -98,11 +123,12 @@ module Xcodeproj
98
123
  #
99
124
  # @return [void]
100
125
  #
101
- def clear_build_files
126
+ def clear
102
127
  files.objects.each do |bf|
103
128
  remove_build_file(bf)
104
129
  end
105
130
  end
131
+ alias :clear_build_files :clear
106
132
 
107
133
  end
108
134
 
@@ -26,11 +26,11 @@ module Xcodeproj
26
26
  #
27
27
  has_many :build_configurations, XCBuildConfiguration
28
28
 
29
- #---------------------------------------------------------------------#
30
29
 
31
30
  public
32
31
 
33
32
  # @!group Helpers
33
+ # --------------------------------------------------------------------#
34
34
 
35
35
  # Returns the build configuration with the given name.
36
36
  #
@@ -158,6 +158,31 @@ module Xcodeproj
158
158
  GroupableHelper.real_path(self)
159
159
  end
160
160
 
161
+ # Sets the source tree of the reference.
162
+ #
163
+ # @param [Symbol, String] source_tree
164
+ # The source tree, either a string or a symbol.
165
+ #
166
+ # @return [void]
167
+ #
168
+ def set_source_tree(source_tree)
169
+ GroupableHelper.set_source_tree(self, source_tree)
170
+ end
171
+
172
+ # Allows to set the path according to the source tree of the reference.
173
+ #
174
+ # @param [#to_s] the path for the reference.
175
+ #
176
+ # @return [void]
177
+ #
178
+ def set_path(path)
179
+ if path
180
+ GroupableHelper.set_path_with_source_tree(self, path, source_tree)
181
+ else
182
+ self.path = nil
183
+ end
184
+ end
185
+
161
186
  # @return [Array<PBXBuildFile>] the build files associated with the
162
187
  # current file reference.
163
188
  #
@@ -78,24 +78,11 @@ module Xcodeproj
78
78
  #
79
79
  attribute :comments, String
80
80
 
81
- #---------------------------------------------------------------------#
82
81
 
83
82
  public
84
83
 
85
84
  # @!group Helpers
86
-
87
- # @return [String] the name of the group taking into account the path
88
- # or other factors if needed.
89
- #
90
- def display_name
91
- if name
92
- name
93
- elsif path
94
- File.basename(path)
95
- elsif self.equal?(project.main_group)
96
- 'Main Group'
97
- end
98
- end
85
+ #---------------------------------------------------------------------#
99
86
 
100
87
  # @return [PBXGroup, PBXProject] The parent of the group.
101
88
  #
@@ -127,13 +114,47 @@ module Xcodeproj
127
114
  GroupableHelper.real_path(self)
128
115
  end
129
116
 
130
- # @return [Array<PBXFileReference>] the files references in the group
117
+ # Sets the source tree of the group.
118
+ #
119
+ # @param [Symbol, String] source_tree
120
+ # The source tree, either a string or a symbol.
121
+ #
122
+ # @return [void]
123
+ #
124
+ def set_source_tree(source_tree)
125
+ GroupableHelper.set_source_tree(self, source_tree)
126
+ end
127
+
128
+ # Allows to set the path according to the source tree of the group.
129
+ #
130
+ # @param [#to_s] the path for the group.
131
+ #
132
+ # @return [void]
133
+ #
134
+ def set_path(path)
135
+ if path
136
+ source_tree
137
+ GroupableHelper.set_path_with_source_tree(self, path, source_tree)
138
+ else
139
+ self.path = nil
140
+ self.source_tree = '<group>'
141
+ end
142
+ end
143
+
144
+ # @return [Array<PBXFileReference>] the file references in the group
131
145
  # children.
132
146
  #
133
147
  def files
134
148
  children.select { |obj| obj.class == PBXFileReference }
135
149
  end
136
150
 
151
+ # @return [PBXFileReference] The file references whose path (regardless
152
+ # of the source tree) matches the give path.
153
+ #
154
+ def find_file_by_path(path)
155
+ files.find { |ref| ref.path == path }
156
+ end
157
+
137
158
  # @return [Array<PBXGroup>] the groups in the group children.
138
159
  #
139
160
  def groups
@@ -219,11 +240,8 @@ module Xcodeproj
219
240
  group = project.new(PBXGroup)
220
241
  children << group
221
242
  group.name = name
222
- if path
223
- GroupableHelper.set_path_with_source_tree(group, path, source_tree)
224
- else
225
- group.source_tree = '<group>'
226
- end
243
+ group.set_source_tree(source_tree)
244
+ group.set_path(path)
227
245
  group
228
246
  end
229
247
 
@@ -238,11 +256,10 @@ module Xcodeproj
238
256
 
239
257
  # Removes children files and groups under this group.
240
258
  #
241
- # @TODO: remove from project should suffice.
242
- #
243
- def remove_children_recursively
259
+ def clear
244
260
  children.objects.each(&:remove_from_project)
245
261
  end
262
+ alias :remove_children_recursively :clear
246
263
 
247
264
  # Traverses the children groups and finds the children with the given
248
265
  # path, optionally, creating any needed group. If the given path is
@@ -303,12 +320,20 @@ module Xcodeproj
303
320
  #
304
321
  def sort_by_type
305
322
  children.sort! do |x, y|
306
- if x.is_a?(PBXGroup) && y.is_a?(PBXFileReference)
323
+ if x.isa == 'PBXGroup' && !(y.isa == 'PBXGroup')
307
324
  -1
308
- elsif x.is_a?(PBXFileReference) && y.is_a?(PBXGroup)
325
+ elsif !(x.isa == 'PBXGroup') && y.isa == 'PBXGroup'
309
326
  1
327
+ elsif x.display_name && y.display_name
328
+ extname_x = File.extname(x.display_name)
329
+ extname_y = File.extname(y.display_name)
330
+ if extname_x != extname_y
331
+ extname_x <=> extname_y
332
+ else
333
+ File.basename(x.display_name, ".*" ) <=> File.basename(y.display_name, ".*" )
334
+ end
310
335
  else
311
- x.display_name <=> y.display_name
336
+ 0
312
337
  end
313
338
  end
314
339
  end
@@ -321,6 +346,32 @@ module Xcodeproj
321
346
  groups.each { |group| group.recursively_sort_by_type }
322
347
  sort_by_type
323
348
  end
349
+
350
+
351
+ public
352
+
353
+ # @!group AbstractObject Hooks
354
+ #---------------------------------------------------------------------#
355
+
356
+ # @return [String] the name of the group taking into account the path
357
+ # or other factors if needed.
358
+ #
359
+ def display_name
360
+ if name
361
+ name
362
+ elsif path
363
+ File.basename(path)
364
+ elsif self.equal?(project.main_group)
365
+ 'Main Group'
366
+ end
367
+ end
368
+
369
+ # Sorts the to many attributes of the object according to the display
370
+ # name.
371
+ #
372
+ def sort
373
+ sort_by_type
374
+ end
324
375
  end
325
376
 
326
377
  #-----------------------------------------------------------------------#
@@ -108,11 +108,10 @@ module Xcodeproj
108
108
  end
109
109
  when 'SOURCE_ROOT'
110
110
  object.project.path.dirname
111
- when '<absolute>', 'BUILT_PRODUCTS_DIR', 'DEVELOPER_DIR'
111
+ when '<absolute>'
112
112
  nil
113
113
  else
114
- raise "[Xcodeproj] Unable to compute the source tree for " \
115
- " `#{object.display_name}`: `#{object.source_tree}`"
114
+ Pathname.new("${#{object.source_tree}}")
116
115
  end
117
116
  end
118
117
 
@@ -128,6 +127,19 @@ module Xcodeproj
128
127
  :sdk_root => 'SDKROOT',
129
128
  }.freeze
130
129
 
130
+ # Sets the source tree of the given object.
131
+ #
132
+ # @param [Symbol, String] source_tree
133
+ # The source tree, either a string or a key for
134
+ # {SOURCE_TREES_BY_KEY}.
135
+ #
136
+ # @return [void]
137
+ #
138
+ def set_source_tree(object, source_tree)
139
+ source_tree = normalize_source_tree(source_tree)
140
+ object.source_tree = source_tree
141
+ end
142
+
131
143
  # Sets the path of the given object according to the provided source
132
144
  # tree key. The path is converted to relative according to the real
133
145
  # path of the source tree for group and project source trees, if both
@@ -140,28 +152,24 @@ module Xcodeproj
140
152
  # @param [#to_s] path
141
153
  # The path.
142
154
  #
143
- # @param [Symbol] source_tree_key
144
- # The source tree type, see {SOURCE_TREES_BY_KEY} for
145
- # acceptable values.
155
+ # @param [Symbol, String] source_tree
156
+ # The source tree, either a string or a key for
157
+ # {SOURCE_TREES_BY_KEY}.
146
158
  #
147
159
  # @return [void]
148
160
  #
149
- def set_path_with_source_tree(object, path, source_tree_key)
161
+ def set_path_with_source_tree(object, path, source_tree)
150
162
  path = Pathname.new(path)
151
- source_tree = SOURCE_TREES_BY_KEY[source_tree_key]
163
+ source_tree = normalize_source_tree(source_tree)
152
164
  object.source_tree = source_tree
153
165
 
154
- unless source_tree
155
- raise "[Xcodeproj] Unrecognized source tree option `#{source_tree_key}` for path `#{path}`"
156
- end
157
-
158
- if source_tree_key == :absolute
166
+ if source_tree == SOURCE_TREES_BY_KEY[:absolute]
159
167
  unless path.absolute?
160
168
  raise "[Xcodeproj] Attempt to set a relative path with an " \
161
169
  "absolute source tree: `#{path}`"
162
170
  end
163
171
  object.path = path.to_s
164
- elsif source_tree_key == :group || source_tree_key == :project
172
+ elsif source_tree == SOURCE_TREES_BY_KEY[:group] || source_tree == SOURCE_TREES_BY_KEY[:project]
165
173
  source_tree_real_path = GroupableHelper.source_tree_real_path(object)
166
174
  if source_tree_real_path && source_tree_real_path.absolute? == path.absolute?
167
175
  relative_path = path.relative_path_from(source_tree_real_path)
@@ -185,7 +193,7 @@ module Xcodeproj
185
193
  # @return [void]
186
194
  #
187
195
  def check_parents_integrity(object)
188
- referrers_count = object.referrers.count
196
+ referrers_count = object.referrers.uniq.count
189
197
  if referrers_count > 1
190
198
  referrers_count = object.referrers.select{ |obj| obj.isa == 'PBXGroup' }.count
191
199
  end
@@ -193,7 +201,7 @@ module Xcodeproj
193
201
  if referrers_count == 0
194
202
  raise "[Xcodeproj] Consistency issue: no parent " \
195
203
  "for object `#{object.display_name}`: "\
196
- "#{object.referrers}"
204
+ "`#{object.referrers.join('`, `')}`"
197
205
  elsif referrers_count > 1
198
206
  raise "[Xcodeproj] Consistency issue: unexpected multiple parents " \
199
207
  "for object `#{object.display_name}`: "\
@@ -201,6 +209,25 @@ module Xcodeproj
201
209
  end
202
210
  end
203
211
 
212
+ # Converts the given source tree to its string value.
213
+ #
214
+ # @param [Symbol, String] source_tree
215
+ # The source tree, either a string or a key for
216
+ # {SOURCE_TREES_BY_KEY}.
217
+ #
218
+ # @return [String] the string value of the source tree.
219
+ #
220
+ def normalize_source_tree(source_tree)
221
+ if source_tree.is_a?(Symbol)
222
+ source_tree = SOURCE_TREES_BY_KEY[source_tree]
223
+ end
224
+
225
+ unless SOURCE_TREES_BY_KEY.values.include?(source_tree)
226
+ raise "[Xcodeproj] Unrecognized source tree option `#{source_tree}`"
227
+ end
228
+ source_tree
229
+ end
230
+
204
231
  #-------------------------------------------------------------------#
205
232
 
206
233
  end
@@ -26,15 +26,16 @@ module Xcodeproj
26
26
  #
27
27
  has_one :build_configuration_list, XCConfigurationList
28
28
 
29
- # @return [PBXNativeTarget] the targets necessary to build this target.
29
+ # @return [ObjectList<PBXTargetDependency>] the targets necessary to
30
+ # build this target.
30
31
  #
31
32
  has_many :dependencies, PBXTargetDependency
32
33
 
33
- #--------------------------------------#
34
34
 
35
35
  public
36
36
 
37
37
  # @!group Helpers
38
+ #--------------------------------------#
38
39
 
39
40
  # @return [String] the SDK that the target should use.
40
41
  #
@@ -137,17 +138,19 @@ module Xcodeproj
137
138
  # @return [void]
138
139
  #
139
140
  def add_dependency(target)
140
- container_proxy = project.new(Xcodeproj::Project::PBXContainerItemProxy)
141
- container_proxy.container_portal = project.root_object.uuid
142
- container_proxy.proxy_type = '1'
143
- container_proxy.remote_global_id_string = target.uuid
144
- container_proxy.remote_info = target.name
145
-
146
- dependency = project.new(Xcodeproj::Project::PBXTargetDependency)
147
- dependency.target = target
148
- dependency.target_proxy = container_proxy
149
-
150
- dependencies << dependency
141
+ unless dependencies.map(&:target).include?(target)
142
+ container_proxy = project.new(Xcodeproj::Project::PBXContainerItemProxy)
143
+ container_proxy.container_portal = project.root_object.uuid
144
+ container_proxy.proxy_type = '1'
145
+ container_proxy.remote_global_id_string = target.uuid
146
+ container_proxy.remote_info = target.name
147
+
148
+ dependency = project.new(Xcodeproj::Project::PBXTargetDependency)
149
+ dependency.target = target
150
+ dependency.target_proxy = container_proxy
151
+
152
+ dependencies << dependency
153
+ end
151
154
  end
152
155
 
153
156
  # Creates a new copy files build phase.
@@ -177,11 +180,56 @@ module Xcodeproj
177
180
  phase
178
181
  end
179
182
 
183
+
184
+ public
185
+
186
+ # @!group System frameworks
180
187
  #--------------------------------------#
181
188
 
189
+ # Adds a file reference for one or more system framework to the project
190
+ # if needed and adds them to the Frameworks build phases.
191
+ #
192
+ # @param [Array<String>, String] name
193
+ # The name or the list of the names of the framework.
194
+ #
195
+ # @return [void]
196
+ #
197
+ def add_system_framework(names)
198
+ Array(names).each do |name|
199
+ path = "System/Library/Frameworks/#{name}.framework"
200
+ unless ref = project.frameworks_group.find_file_by_path(path)
201
+ ref = project.frameworks_group.new_file(path, :sdk_root)
202
+ end
203
+ frameworks_build_phase.add_file_reference(ref, true)
204
+ ref
205
+ end
206
+ end
207
+ alias :add_system_frameworks :add_system_framework
208
+
209
+ # Adds a file reference for one or more system libraries to the project
210
+ # if needed and adds them to the Frameworks build phases.
211
+ #
212
+ # @param [Array<String>, String] name
213
+ # The name or the list of the names of the libraries.
214
+ #
215
+ # @return [void]
216
+ #
217
+ def add_system_library(names)
218
+ Array(names).each do |name|
219
+ path = "usr/lib/lib#{name}.dylib"
220
+ unless ref = project.frameworks_group.files.find { |ref| ref.path == path }
221
+ ref = project.frameworks_group.new_file(path, :sdk_root)
222
+ end
223
+ frameworks_build_phase.add_file_reference(ref, true)
224
+ ref
225
+ end
226
+ end
227
+ alias :add_system_libraries :add_system_library
228
+
182
229
  public
183
230
 
184
231
  # @!group AbstractObject Hooks
232
+ #--------------------------------------#
185
233
 
186
234
  # @return [Hash{String => Hash}] A hash suitable to display the object
187
235
  # to the user.
@@ -221,7 +269,8 @@ module Xcodeproj
221
269
  #
222
270
  attribute :product_install_path, String
223
271
 
224
- # @return [PBXBuildRule] the build phases of the target.
272
+ # @return [ObjectList<AbstractBuildPhase>] the build phases of the
273
+ # target.
225
274
  #
226
275
  # @note Apparently only PBXCopyFilesBuildPhase and
227
276
  # PBXShellScriptBuildPhase can appear multiple times in a
@@ -229,11 +278,11 @@ module Xcodeproj
229
278
  #
230
279
  has_many :build_phases, AbstractBuildPhase
231
280
 
232
- #--------------------------------------#
233
281
 
234
282
  public
235
283
 
236
284
  # @!group Helpers
285
+ #--------------------------------------#
237
286
 
238
287
  # Adds source files to the target.
239
288
  #
@@ -349,6 +398,26 @@ module Xcodeproj
349
398
  phase
350
399
  end
351
400
 
401
+
402
+ public
403
+
404
+ # @!group AbstractObject Hooks
405
+ #--------------------------------------#
406
+
407
+ # Sorts the to many attributes of the object according to the display
408
+ # name.
409
+ #
410
+ # Build phases are not sorted as they order is relevant.
411
+ #
412
+ def sort
413
+ attributes_to_sort = to_many_attributes.reject { |attr| attr.name == :build_phases }
414
+ attributes_to_sort.each do |attrb|
415
+ list = attrb.get_value(self)
416
+ list.sort! do |x, y|
417
+ x.display_name <=> y.display_name
418
+ end
419
+ end
420
+ end
352
421
  end
353
422
 
354
423
  #-----------------------------------------------------------------------#
@@ -27,6 +27,20 @@ module Xcodeproj
27
27
  # target from a nested Xcode project.
28
28
  #
29
29
  attribute :name, String
30
+
31
+
32
+ public
33
+
34
+ # @!group AbstractObject Hooks
35
+ #--------------------------------------#
36
+
37
+ # @return [String] The name of the dependency.
38
+ #
39
+ def display_name
40
+ return name if name
41
+ return target.name if target
42
+ return target_proxy.remote_info if target_proxy
43
+ end
30
44
  end
31
45
  end
32
46
  end
@@ -61,10 +61,17 @@ module Xcodeproj
61
61
  # `_id_` would become `Id`
62
62
  'remoteGlobalIDString'
63
63
  else
64
- name.to_s.camelize(:lower)
64
+ self.class.plist_name_store[name] ||= name.to_s.camelize(:lower)
65
65
  end
66
66
  end
67
67
 
68
+ # @return [Hash] a shared store which cahces the plist name of the
69
+ # attributes.
70
+ #
71
+ def self.plist_name_store
72
+ @plist_name_store ||= {}
73
+ end
74
+
68
75
  # @return [Array<Class>] the list of the classes accepted by the
69
76
  # attribute.
70
77
  #
@@ -34,10 +34,6 @@ module Xcodeproj
34
34
  #
35
35
  attr_reader :owner
36
36
 
37
- #------------------------------------------------------------------------#
38
-
39
- # @!group ObjectList
40
-
41
37
  # @return [Array<String>]
42
38
  # the UUIDs of all the objects referenced by this list.
43
39
  #
@@ -52,9 +48,11 @@ module Xcodeproj
52
48
  to_a
53
49
  end
54
50
 
55
- #------------------------------------------------------------------------#
51
+
52
+ public
56
53
 
57
54
  # @!group Notification enabled methods
55
+ #------------------------------------------------------------------------#
58
56
 
59
57
  # TODO: the overridden methods are incomplete.
60
58
 
@@ -66,11 +64,11 @@ module Xcodeproj
66
64
  # @return [void]
67
65
  #
68
66
  def +(objects)
69
- super
70
67
  perform_additions_operations(objects)
68
+ super
71
69
  end
72
70
 
73
- # Adds an object to list the and updates its references count.
71
+ # Appends an object to list the and updates its references count.
74
72
  #
75
73
  # @param [AbstractObject, ObjectDictionary] object
76
74
  # The object to add to the list.
@@ -78,8 +76,21 @@ module Xcodeproj
78
76
  # @return [void]
79
77
  #
80
78
  def <<(object)
79
+ perform_additions_operations(object)
81
80
  super
81
+ end
82
+
83
+ # Adds an object to the given index of the list the and updates its
84
+ # references count.
85
+ #
86
+ # @param [AbstractObject, ObjectDictionary] object
87
+ # The object to add to the list.
88
+ #
89
+ # @return [void]
90
+ #
91
+ def insert(index, object)
82
92
  perform_additions_operations(object)
93
+ super
83
94
  end
84
95
 
85
96
  # Prepends an object to the list and updates its references count.
@@ -90,8 +101,8 @@ module Xcodeproj
90
101
  # @return [void]
91
102
  #
92
103
  def unshift(object)
93
- super
94
104
  perform_additions_operations(object)
105
+ super
95
106
  end
96
107
 
97
108
  # Removes an object to list and updates its references count.
@@ -99,11 +110,25 @@ module Xcodeproj
99
110
  # @param [AbstractObject, ObjectDictionary] object
100
111
  # the object to delete from the list.
101
112
  #
102
- # @return [void]
113
+ # @return [AbstractObject, ObjectDictionary, Nil] the object if found.
103
114
  #
104
115
  def delete(object)
116
+ perform_deletion_operations(object)
105
117
  super
118
+ end
119
+
120
+ # Removes the object at the given index from the list and updates its
121
+ # references count.
122
+ #
123
+ # @param [Fixnum] from
124
+ # The index of the object.
125
+ #
126
+ # @return [AbstractObject, ObjectDictionary, Nil] the object if found.
127
+ #
128
+ def delete_at(index)
129
+ object = at(index)
106
130
  perform_deletion_operations(object)
131
+ super
107
132
  end
108
133
 
109
134
  # Removes all the objects contained in the list and updates their
@@ -118,12 +143,48 @@ module Xcodeproj
118
143
  super
119
144
  end
120
145
 
121
- #------------------------------------------------------------------------#
146
+ # Moves the object at the given given index to the given position.
147
+ #
148
+ # @param [Fixnum] from
149
+ # The current index of the object.
150
+ #
151
+ # @param [Fixnum] to
152
+ # The new index for the object.
153
+ #
154
+ # @return [void]
155
+ #
156
+ def move(object, new_index)
157
+ if obj = delete(object)
158
+ insert(new_index, obj)
159
+ else
160
+ raise "Attempt to move object `#{object}` not present in the list `#{self.inspect}`"
161
+ end
162
+ end
163
+
164
+ # Moves the object at the given given index to the given position.
165
+ #
166
+ # @param [Fixnum] from
167
+ # The current index of the object.
168
+ #
169
+ # @param [Fixnum] to
170
+ # The new index for the object.
171
+ #
172
+ # @return [void]
173
+ #
174
+ def move_from(current_index, new_index)
175
+ if obj = delete_at(current_index)
176
+ insert(new_index, obj)
177
+ else
178
+ raise "Attempt to move object from index `#{current_index}` which is beyond bounds of the list `#{self.inspect}`"
179
+ end
180
+ end
122
181
 
123
- # @!group Notification Methods
124
182
 
125
183
  private
126
184
 
185
+ # @!group Notification Methods
186
+ #------------------------------------------------------------------------#
187
+
127
188
  # Informs an object that it was added to the list. In practice it adds
128
189
  # the owner of the list as referrer to the objects. It also validates the
129
190
  # value.
@@ -55,7 +55,7 @@ module Xcodeproj
55
55
 
56
56
  # Frameworks
57
57
  framework_name = (platform == :ios) ? 'Foundation' : 'Cocoa'
58
- framework_ref = project.add_system_framework(framework_name, target)
58
+ framework_ref = target.add_system_framework(framework_name)
59
59
 
60
60
  target
61
61
  end
@@ -115,55 +115,6 @@ module Xcodeproj
115
115
  target
116
116
  end
117
117
 
118
- # @!group System Frameworks
119
-
120
- #-----------------------------------------------------------------------#
121
-
122
- # Adds a file reference for a system framework to the project if needed
123
- # and adds it to the {PBXFrameworksBuildPhase} of the given target.
124
- #
125
- # @param [Project] project
126
- # the project to which the configuration list should be added.
127
- #
128
- # @param [String] name
129
- # The name of a framework.
130
- #
131
- # @param [PBXNativeTarget] target
132
- # The target to which to add the framework.
133
- #
134
- # @note This method adds a reference to the highest know SDK for the
135
- # given platform.
136
- #
137
- # @return [PBXFileReference] The file reference of the framework.
138
- #
139
- def self.add_system_framework(project, name, target)
140
- sdk = target.sdk
141
- raise "Unable to find and SDK for the target `#{target.name}`" unless sdk
142
- if sdk.include?('iphoneos')
143
- if sdk == 'iphoneos'
144
- version = XcodebuildHelper.instance.last_ios_sdk || Constants::LAST_KNOWN_IOS_SDK
145
- base_dir = "Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS#{version}.sdk/"
146
- else
147
- base_dir = "Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS#{sdk.gsub('iphoneos', '')}.sdk/"
148
- end
149
- elsif sdk.include?('macosx')
150
- if sdk == 'macosx'
151
- version = XcodebuildHelper.instance.last_osx_sdk || Constants::LAST_KNOWN_OSX_SDK
152
- base_dir = "Platforms/MacOSX.platform/Developer/SDKs/MacOSX#{version}.sdk/"
153
- else
154
- base_dir = "Platforms/MacOSX.platform/Developer/SDKs/MacOSX#{sdk.gsub('macosx', '')}.sdk/"
155
- end
156
- end
157
-
158
- path = base_dir + "System/Library/Frameworks/#{name}.framework"
159
- ref = project.frameworks_group.files.find { |f| f.path == path }
160
- unless ref
161
- ref = project.frameworks_group.new_file(path, :developer_dir)
162
- end
163
-
164
- target.frameworks_build_phase.add_file_reference(ref)
165
- ref
166
- end
167
118
 
168
119
  # @!group Private Helpers
169
120
 
@@ -18,7 +18,7 @@ module Xcodeproj
18
18
  #
19
19
  def touch(path)
20
20
  if available?
21
- command = "xcproj --project #{path} touch"
21
+ command = "xcproj --project \"#{path}\" touch"
22
22
  success, output = execute(command)
23
23
  unless success
24
24
  message = "xcproj failed to touch the project. Check whether you installation of xcproj is functional.\n\n"
@@ -51,7 +51,7 @@ module Xcodeproj
51
51
  def self.from_s(xml, workspace_path='')
52
52
  document = REXML::Document.new(xml)
53
53
  projpaths = document.get_elements("/Workspace/FileRef").map do |node|
54
- node.attribute("location").to_s.sub(/^group:/, '')
54
+ node.attribute("location").value.sub(/^group:/, '')
55
55
  end
56
56
  instance = new(projpaths)
57
57
  instance.load_schemes(workspace_path)
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: 0.10.1
4
+ version: 0.11.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: 2013-09-04 00:00:00.000000000 Z
11
+ date: 2013-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -50,6 +50,7 @@ extra_rdoc_files: []
50
50
  files:
51
51
  - lib/xcodeproj/command/project_diff.rb
52
52
  - lib/xcodeproj/command/show.rb
53
+ - lib/xcodeproj/command/sort.rb
53
54
  - lib/xcodeproj/command/target_diff.rb
54
55
  - lib/xcodeproj/command.rb
55
56
  - lib/xcodeproj/config.rb