xcodeproj 1.3.3 → 1.4.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: 04c4429d5bd1901ac79b9057825d4506a3d4677a
4
- data.tar.gz: 41170f0792b8529c15600b5837f94949f0114cfb
3
+ metadata.gz: c1d9e25f8e263946cf8049c3fd87d32eb60774e2
4
+ data.tar.gz: 1aa69336dac41f7c9192ee45b11157bf2d6ab372
5
5
  SHA512:
6
- metadata.gz: bd83e86802491f25727e5ea74b1ff9d4edab9cb183254cb89482dd92998bc6ef96051d7a2f43be7d51e1e9dd5d635950d3c61f95e8dc253696b9b43112516553
7
- data.tar.gz: 549778943ec9f0d3a9cea8277be5fe90b71b16d5c9404c17917a66caa5a49430bceedd652ccb30244189855aecc96ccb83f60aa52a773f639cdb95eafb4ed42a
6
+ metadata.gz: c7ddb7c072f0d6ccf2af6bbb5dd1c6093007986edd5f91802ea4d304dcf373d0385a161ae74584b99de9ffa06f37364c39435cb96cb6ba6dbae5b1c597452058
7
+ data.tar.gz: 01eff04f86c6cfe00adea390ef346c0a2650447dd8a324b624ac3d070a54329afa6b2a20cbb217b24d0a318e62db6193eb10aa22f9ebf9c16b85928fcd75dae7
@@ -1,5 +1,5 @@
1
1
  module Xcodeproj
2
2
  # The version of the xcodeproj gem.
3
3
  #
4
- VERSION = '1.3.3'.freeze unless defined? Xcodeproj::VERSION
4
+ VERSION = '1.4.0'.freeze unless defined? Xcodeproj::VERSION
5
5
  end
@@ -1,10 +1,10 @@
1
+ autoload :Nanaimo, 'nanaimo'
2
+ autoload :CFPropertyList, 'cfpropertylist'
3
+
1
4
  module Xcodeproj
2
5
  # Provides support for loading and serializing property list files.
3
6
  #
4
7
  module Plist
5
- autoload :FFI, 'xcodeproj/plist/ffi'
6
- autoload :PlistGem, 'xcodeproj/plist/plist_gem'
7
-
8
8
  # @return [Hash] Returns the native objects loaded from a property list
9
9
  # file.
10
10
  #
@@ -16,10 +16,16 @@ module Xcodeproj
16
16
  unless File.exist?(path)
17
17
  raise Informative, "The plist file at path `#{path}` doesn't exist."
18
18
  end
19
- if file_in_conflict?(path)
19
+ contents = File.read(path)
20
+ if file_in_conflict?(contents)
20
21
  raise Informative, "The file `#{path}` is in a merge conflict."
21
22
  end
22
- implementation.read_from_path(path)
23
+ case Nanaimo::Reader.plist_type(contents)
24
+ when :xml, :binary
25
+ CFPropertyList.native_types(CFPropertyList::List.new(:data => contents).value)
26
+ else
27
+ Nanaimo::Reader.new(contents).parse!.as_ruby
28
+ end
23
29
  end
24
30
 
25
31
  # Serializes a hash as an XML property list file.
@@ -43,47 +49,39 @@ module Xcodeproj
43
49
  end
44
50
  path = path.to_s
45
51
  raise IOError, 'Empty path.' if path.empty?
46
- implementation.write_to_path(hash, path)
52
+
53
+ File.open(path, 'w') do |f|
54
+ plist = Nanaimo::Plist.new(hash, :xml)
55
+ Nanaimo::Writer::XMLWriter.new(plist, true, f).write
56
+ end
47
57
  end
48
58
 
49
59
  # The known modules that can serialize plists.
50
60
  #
51
- KNOWN_IMPLEMENTATIONS = [:FFI, :PlistGem]
61
+ KNOWN_IMPLEMENTATIONS = []
52
62
 
53
63
  class << self
54
- # @return The module used to implement plist serialization.
64
+ # @deprecated This method will be removed in 2.0
65
+ #
66
+ # @return [Nil]
55
67
  #
56
68
  attr_accessor :implementation
57
- def implementation
58
- @implementation ||= autoload_implementation
59
- end
60
69
  end
61
70
 
62
- # Attempts to autoload a known plist implementation.
71
+ # @deprecated This method will be removed in 2.0
63
72
  #
64
- # @return a successfully loaded plist serialization implementation.
73
+ # @return [Nil]
65
74
  #
66
75
  def self.autoload_implementation
67
- failures = KNOWN_IMPLEMENTATIONS.map do |impl|
68
- begin
69
- impl = Plist.const_get(impl)
70
- failure = impl.attempt_to_load!
71
- return impl if failure.nil?
72
- failure
73
- rescue NameError, LoadError => e
74
- e.message
75
- end
76
- end.compact
77
- raise Informative, "Unable to load a plist implementation:\n\n#{failures.join("\n\n")}"
78
76
  end
79
77
 
80
78
  # @return [Bool] Checks whether there are merge conflicts in the file.
81
79
  #
82
80
  # @param [#to_s] path
83
- # The path of the file.
81
+ # The contents of the file.
84
82
  #
85
- def self.file_in_conflict?(path)
86
- File.read(path).match(/^(<|=|>){7}/)
83
+ def self.file_in_conflict?(contents)
84
+ contents.match(/^(<|=|>){7}/)
87
85
  end
88
86
  end
89
87
  end
@@ -277,6 +277,24 @@ module Xcodeproj
277
277
  plist
278
278
  end
279
279
 
280
+ def to_ascii_plist
281
+ plist = {}
282
+ objects_dictionary = {}
283
+ objects
284
+ .sort_by { |o| [o.isa, o.uuid] }
285
+ .each do |obj|
286
+ key = Nanaimo::String.new(obj.uuid, obj.ascii_plist_annotation)
287
+ value = obj.to_ascii_plist.tap { |a| a.annotation = nil }
288
+ objects_dictionary[key] = value
289
+ end
290
+ plist['archiveVersion'] = archive_version.to_s
291
+ plist['classes'] = classes
292
+ plist['objectVersion'] = object_version.to_s
293
+ plist['objects'] = objects_dictionary
294
+ plist['rootObject'] = Nanaimo::String.new(root_object.uuid, root_object.ascii_plist_annotation)
295
+ Nanaimo::Plist.new.tap { |p| p.root_object = plist }
296
+ end
297
+
280
298
  # Converts the objects tree to a hash substituting the hash
281
299
  # of the referenced to their UUID reference. As a consequence the hash of
282
300
  # an object might appear multiple times and the information about their
@@ -332,7 +350,7 @@ module Xcodeproj
332
350
  @dirty = false if save_path == path
333
351
  FileUtils.mkdir_p(save_path)
334
352
  file = File.join(save_path, 'project.pbxproj')
335
- Plist.write_to_path(to_hash, file)
353
+ File.open(file, 'w') { |f| Nanaimo::XcodeProjectWriter.new(to_ascii_plist, true, f).write }
336
354
  end
337
355
 
338
356
  # Marks the project as dirty, that is, modified from what is on disk.
@@ -373,6 +373,10 @@ module Xcodeproj
373
373
  # array.
374
374
  #
375
375
  def to_hash
376
+ to_hash_as
377
+ end
378
+
379
+ def to_hash_as(method = :to_hash)
376
380
  plist = {}
377
381
  plist['isa'] = isa
378
382
 
@@ -383,21 +387,39 @@ module Xcodeproj
383
387
 
384
388
  to_one_attributes.each do |attrb|
385
389
  obj = attrb.get_value(self)
386
- plist[attrb.plist_name] = obj.uuid if obj
390
+ plist[attrb.plist_name] = nested_object_for_hash(obj, method) if obj
387
391
  end
388
392
 
389
393
  to_many_attributes.each do |attrb|
390
394
  list = attrb.get_value(self)
391
- plist[attrb.plist_name] = list.uuids
395
+ plist[attrb.plist_name] = list.map { |o| nested_object_for_hash(o, method) }
392
396
  end
393
397
 
394
398
  references_by_keys_attributes.each do |attrb|
395
399
  list = attrb.get_value(self)
396
- plist[attrb.plist_name] = list.map(&:to_hash)
400
+ plist[attrb.plist_name] = list.map(&method)
397
401
  end
398
402
 
399
403
  plist
400
404
  end
405
+ private :to_hash_as
406
+
407
+ def nested_object_for_hash(object, method)
408
+ case method
409
+ when :to_ascii_plist
410
+ Nanaimo::String.new(object.uuid, object.ascii_plist_annotation)
411
+ else
412
+ object.uuid
413
+ end
414
+ end
415
+
416
+ def ascii_plist_annotation
417
+ " #{display_name} "
418
+ end
419
+
420
+ def to_ascii_plist
421
+ Nanaimo::Dictionary.new(to_hash_as(:to_ascii_plist), ascii_plist_annotation)
422
+ end
401
423
 
402
424
  # Returns a cascade representation of the object without UUIDs.
403
425
  #
@@ -38,6 +38,12 @@ module Xcodeproj
38
38
  { name => data }
39
39
  end
40
40
 
41
+ def to_hash_as(method = :to_hash)
42
+ super.tap do |hash|
43
+ normalize_array_settings(hash['buildSettings'])
44
+ end
45
+ end
46
+
41
47
  # Sorts the build settings. Valid only in Ruby > 1.9.2 because in
42
48
  # previous versions the hash are not sorted.
43
49
  #
@@ -74,6 +80,52 @@ module Xcodeproj
74
80
  sorted
75
81
  end
76
82
 
83
+ # yes, they are case-sensitive.
84
+ # no, Xcode doesn't do this for other PathList settings nor other
85
+ # settings ending in SEARCH_PATHS.
86
+ ARRAY_SETTINGS = %w(
87
+ ALTERNATE_PERMISSIONS_FILES
88
+ ARCHS
89
+ BUILD_VARIANTS
90
+ EXCLUDED_SOURCE_FILE_NAMES
91
+ FRAMEWORK_SEARCH_PATHS
92
+ GCC_PREPROCESSOR_DEFINITIONS
93
+ GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS
94
+ HEADER_SEARCH_PATHS
95
+ INFOPLIST_PREPROCESSOR_DEFINITIONS
96
+ LIBRARY_SEARCH_PATHS
97
+ OTHER_CFLAGS
98
+ OTHER_CPLUSPLUSFLAGS
99
+ OTHER_LDFLAGS
100
+ REZ_SEARCH_PATHS
101
+ SECTORDER_FLAGS
102
+ WARNING_CFLAGS
103
+ WARNING_LDFLAGS
104
+ ).freeze
105
+ private_constant :ARRAY_SETTINGS
106
+
107
+ def normalize_array_settings(settings)
108
+ return unless settings
109
+ settings.keys.each do |key|
110
+ next unless value = settings[key]
111
+ case value
112
+ when String
113
+ next unless ARRAY_SETTINGS.include?(key)
114
+ array_value = split_build_setting_array_to_string(value)
115
+ next unless array_value.size > 1
116
+ settings[key] = array_value
117
+ when Array
118
+ next if value.size > 1 && ARRAY_SETTINGS.include?(key)
119
+ settings[key] = value.join(' ')
120
+ end
121
+ end
122
+ end
123
+
124
+ def split_build_setting_array_to_string(string)
125
+ regexp = / *((['"]?).*?[^\\]\2)(?=( |\z))/
126
+ string.scan(regexp).map(&:first)
127
+ end
128
+
77
129
  #---------------------------------------------------------------------#
78
130
  end
79
131
  end
@@ -59,6 +59,10 @@ module Xcodeproj
59
59
  end
60
60
  end
61
61
 
62
+ def ascii_plist_annotation
63
+ " #{display_name} in #{GroupableHelper.parent(self).display_name} "
64
+ end
65
+
62
66
  #---------------------------------------------------------------------#
63
67
  end
64
68
  end
@@ -127,6 +127,14 @@ module Xcodeproj
127
127
  end
128
128
  end
129
129
  alias_method :clear_build_files, :clear
130
+
131
+ def display_name
132
+ super.gsub(/BuildPhase$/, '')
133
+ end
134
+
135
+ def ascii_plist_annotation
136
+ " #{display_name} "
137
+ end
130
138
  end
131
139
 
132
140
  #-----------------------------------------------------------------------#
@@ -80,6 +80,10 @@ module Xcodeproj
80
80
  def output_files_and_flags
81
81
  (output_files || []).zip(output_files_compiler_flags || [])
82
82
  end
83
+
84
+ def ascii_plist_annotation
85
+ " #{isa} "
86
+ end
83
87
  end
84
88
  end
85
89
  end
@@ -90,7 +90,16 @@ module Xcodeproj
90
90
  end
91
91
  end
92
92
 
93
+ def target
94
+ return project.root_object if project.build_configuration_list.uuid == uuid
95
+ project.targets.find { |t| t.build_configuration_list.uuid == uuid }
96
+ end
97
+
93
98
  #---------------------------------------------------------------------#
99
+
100
+ def ascii_plist_annotation
101
+ " Build configuration list for #{target.isa} \"#{target}\" "
102
+ end
94
103
  end
95
104
  end
96
105
  end
@@ -79,13 +79,36 @@ module Xcodeproj
79
79
  # @return [AbstractObject]
80
80
  #
81
81
  def proxied_object
82
+ container_portal_object.objects_by_uuid[remote_global_id_string]
83
+ end
84
+
85
+ def container_portal_object
82
86
  if remote?
83
87
  container_portal_file_ref = project.objects_by_uuid[container_portal]
84
- container_portal_object = Project.open(container_portal_file_ref.real_path)
88
+ Project.open(container_portal_file_ref.real_path)
85
89
  else
86
- container_portal_object = project
90
+ project
87
91
  end
88
- container_portal_object.objects_by_uuid[remote_global_id_string]
92
+ end
93
+
94
+ def container_portal_annotation
95
+ if remote?
96
+ " #{File.basename(project.objects_by_uuid[container_portal].real_path)} "
97
+ else
98
+ project.root_object.ascii_plist_annotation
99
+ end
100
+ end
101
+
102
+ def to_hash_as(method = :to_hash)
103
+ hash = super
104
+ if method == :to_ascii_plist
105
+ hash['containerPortal'] = Nanaimo::String.new(container_portal, container_portal_annotation)
106
+ end
107
+ hash
108
+ end
109
+
110
+ def ascii_plist_annotation
111
+ " #{isa} "
89
112
  end
90
113
  end
91
114
  end
@@ -123,7 +123,13 @@ module Xcodeproj
123
123
  # needed.
124
124
  #
125
125
  def display_name
126
- name || (File.basename(path) if path)
126
+ if name
127
+ name
128
+ elsif (class << GroupableHelper; self; end)::SOURCE_TREES_BY_KEY[:built_products] == source_tree
129
+ path
130
+ elsif path
131
+ File.basename(path)
132
+ end
127
133
  end
128
134
 
129
135
  # @return [PBXGroup, PBXProject] the parent of the file.
@@ -412,6 +412,10 @@ module Xcodeproj
412
412
  end
413
413
  end
414
414
 
415
+ def ascii_plist_annotation
416
+ super unless self.equal?(project.main_group)
417
+ end
418
+
415
419
  # Sorts the to many attributes of the object according to the display
416
420
  # name.
417
421
  #
@@ -48,6 +48,10 @@ module Xcodeproj
48
48
  end
49
49
 
50
50
  #---------------------------------------------------------------------#
51
+
52
+ def ascii_plist_annotation
53
+ " #{name || path && File.basename(path)} "
54
+ end
51
55
  end
52
56
  end
53
57
  end
@@ -67,6 +67,20 @@ module Xcodeproj
67
67
  has_many_references_by_keys :project_references,
68
68
  :project_ref => PBXFileReference,
69
69
  :product_group => PBXGroup
70
+
71
+ def name
72
+ project.path.basename('.xcodeproj').to_s
73
+ end
74
+
75
+ def ascii_plist_annotation
76
+ ' Project object '
77
+ end
78
+
79
+ def to_ascii_plist
80
+ plist = super
81
+ plist.value.delete('projectReferences') if plist.value['projectReferences'].empty?
82
+ plist
83
+ end
70
84
  end
71
85
  end
72
86
  end
@@ -39,6 +39,10 @@ module Xcodeproj
39
39
  return target_proxy.remote_info if target_proxy
40
40
  end
41
41
 
42
+ def ascii_plist_annotation
43
+ " #{isa} "
44
+ end
45
+
42
46
  # @return [String] uuid of the target, if the dependency
43
47
  # is a native target, otherwise the uuid of the
44
48
  # target in the sub-project if the dependency is
@@ -117,12 +117,16 @@ module Xcodeproj
117
117
  each do |key, obj|
118
118
  if obj
119
119
  plist_key = Object::CaseConverter.convert_to_plist(key, nil)
120
- result[plist_key] = obj.uuid
120
+ result[plist_key] = Nanaimo::String.new(obj.uuid, obj.ascii_plist_annotation)
121
121
  end
122
122
  end
123
123
  result
124
124
  end
125
125
 
126
+ def to_ascii_plist
127
+ to_hash
128
+ end
129
+
126
130
  # @return [Hash<String => String>] Returns a cascade representation of
127
131
  # the object without UUIDs.
128
132
  #