xcodeproj 0.10.1 → 0.11.0

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
  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