xcodeproj 0.3.5 → 0.4.0.rc1

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.
Files changed (32) hide show
  1. data/bin/xcodeproj +13 -0
  2. data/lib/xcodeproj.rb +13 -1
  3. data/lib/xcodeproj/command.rb +131 -0
  4. data/lib/xcodeproj/command/project_diff.rb +53 -0
  5. data/lib/xcodeproj/command/show.rb +35 -0
  6. data/lib/xcodeproj/command/target_diff.rb +43 -0
  7. data/lib/xcodeproj/config.rb +66 -38
  8. data/lib/xcodeproj/constants.rb +146 -0
  9. data/lib/xcodeproj/helper.rb +28 -0
  10. data/lib/xcodeproj/project.rb +462 -156
  11. data/lib/xcodeproj/project/object.rb +251 -138
  12. data/lib/xcodeproj/project/object/build_configuration.rb +27 -0
  13. data/lib/xcodeproj/project/object/build_file.rb +26 -0
  14. data/lib/xcodeproj/project/object/build_phase.rb +132 -61
  15. data/lib/xcodeproj/project/object/build_rule.rb +46 -0
  16. data/lib/xcodeproj/project/object/configuration_list.rb +47 -0
  17. data/lib/xcodeproj/project/object/container_item_proxy.rb +49 -0
  18. data/lib/xcodeproj/project/object/file_reference.rb +80 -48
  19. data/lib/xcodeproj/project/object/group.rb +213 -89
  20. data/lib/xcodeproj/project/object/native_target.rb +171 -114
  21. data/lib/xcodeproj/project/object/root_object.rb +66 -0
  22. data/lib/xcodeproj/project/object/target_dependency.rb +23 -0
  23. data/lib/xcodeproj/project/object_attributes.rb +382 -0
  24. data/lib/xcodeproj/project/object_list.rb +64 -118
  25. data/lib/xcodeproj/project/recursive_diff.rb +116 -0
  26. data/lib/xcodeproj/workspace.rb +56 -2
  27. metadata +38 -10
  28. data/lib/xcodeproj/project/association.rb +0 -54
  29. data/lib/xcodeproj/project/association/has_many.rb +0 -51
  30. data/lib/xcodeproj/project/association/has_one.rb +0 -39
  31. data/lib/xcodeproj/project/association/reflection.rb +0 -86
  32. data/lib/xcodeproj/project/object/configuration.rb +0 -97
data/bin/xcodeproj ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if $0 == __FILE__
4
+ ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
5
+ require "rubygems"
6
+ require "bundler/setup"
7
+ $:.unshift File.expand_path('../../ext', __FILE__)
8
+ $:.unshift File.expand_path('../../lib', __FILE__)
9
+ end
10
+
11
+ require 'xcodeproj'
12
+
13
+ Xcodeproj::Command.run(*ARGV)
data/lib/xcodeproj.rb CHANGED
@@ -1,7 +1,19 @@
1
1
  module Xcodeproj
2
- VERSION = '0.3.5'
2
+ VERSION = '0.4.0.rc1'
3
+
4
+ class PlainInformative < StandardError
5
+ end
6
+
7
+ class Informative < PlainInformative
8
+ def message
9
+ super !~ /\[!\]/ ? "[!] #{super}\n".red : super
10
+ end
11
+ end
3
12
 
4
13
  autoload :Config, 'xcodeproj/config'
14
+ autoload :Command, 'xcodeproj/command'
15
+ autoload :Constants, 'xcodeproj/constants'
16
+ autoload :Helper, 'xcodeproj/helper'
5
17
  autoload :Project, 'xcodeproj/project'
6
18
  autoload :Workspace, 'xcodeproj/workspace'
7
19
  end
@@ -0,0 +1,131 @@
1
+ module Xcodeproj
2
+
3
+ require 'colored'
4
+
5
+ class Command
6
+ autoload :TargetDiff, 'xcodeproj/command/target_diff'
7
+ autoload :ProjectDiff, 'xcodeproj/command/project_diff'
8
+ autoload :Show, 'xcodeproj/command/show'
9
+
10
+ class Help < StandardError
11
+ def initialize(command_class, argv, unrecognized_command = nil)
12
+ @command_class, @argv, @unrecognized_command = command_class, argv, unrecognized_command
13
+ end
14
+
15
+ def message
16
+ message = [
17
+ '',
18
+ @command_class.banner.gsub(/\$ pod (.*)/, '$ pod \1'.green),
19
+ '',
20
+ 'Options:',
21
+ '',
22
+ options,
23
+ "\n",
24
+ ].join("\n")
25
+ message << "[!] Unrecognized command: `#{@unrecognized_command}'\n".red if @unrecognized_command
26
+ message << "[!] Unrecognized argument#{@argv.count > 1 ? 's' : ''}: `#{@argv.join(' - ')}'\n".red unless @argv.empty?
27
+ message
28
+ end
29
+
30
+ private
31
+
32
+ def options
33
+ options = @command_class.options
34
+ keys = options.map(&:first)
35
+ key_size = keys.inject(0) { |size, key| key.size > size ? key.size : size }
36
+ options.map { |key, desc| " #{key.ljust(key_size)} #{desc}" }.join("\n")
37
+ end
38
+ end
39
+
40
+ class ARGV < Array
41
+ def options; select { |x| x.to_s[0,1] == '-' }; end
42
+ def arguments; self - options; end
43
+ def option(name); !!delete(name); end
44
+ def shift_argument; (arg = arguments[0]) && delete(arg); end
45
+ end
46
+
47
+ def self.banner
48
+ commands = ['target-diff', 'project-diff', 'show']
49
+ banner = "To see help for the available commands run:\n\n"
50
+ banner + commands.map { |cmd| " * $ xcodeproj #{cmd.green} --help" }.join("\n")
51
+ end
52
+
53
+ def self.options
54
+ [
55
+ ['--help', 'Show help information'],
56
+ # ['--silent', 'Print nothing'],
57
+ # ['--no-color', 'Print output without color'],
58
+ # ['--verbose', 'Print more information while working'],
59
+ ['--version', 'Prints the version of CocoaPods'],
60
+ ]
61
+ end
62
+
63
+ def self.run(*argv)
64
+ sub_command = parse(*argv)
65
+ sub_command.run
66
+
67
+ rescue Interrupt
68
+ puts "[!] Cancelled".red
69
+ Config.instance.verbose? ? raise : exit(1)
70
+
71
+ rescue Exception => e
72
+ puts e.message
73
+ puts *e.backtrace
74
+ exit 1
75
+ end
76
+
77
+ def self.parse(*argv)
78
+ argv = ARGV.new(argv)
79
+ if argv.option('--version')
80
+ puts VERSION
81
+ exit!(0)
82
+ end
83
+
84
+ show_help = argv.option('--help')
85
+
86
+ String.send(:define_method, :colorize) { |string , _| string } if argv.option( '--no-color' )
87
+
88
+ command_class = case command_argument = argv.shift_argument
89
+ when 'target-diff' then TargetDiff
90
+ when 'project-diff' then ProjectDiff
91
+ when 'show' then Show
92
+ end
93
+
94
+ if command_class.nil?
95
+ raise Help.new(self, argv, command_argument)
96
+ elsif show_help
97
+ raise Help.new(command_class, argv)
98
+ else
99
+ command_class.new(argv)
100
+ end
101
+ end
102
+
103
+ def initialize(argv)
104
+ raise Help.new(self.class, argv)
105
+ end
106
+
107
+ def xcodeproj_path
108
+ unless @xcodeproj_path
109
+ projects = Dir.glob('*.xcodeproj')
110
+ if projects.size == 1
111
+ xcodeproj_path = projects.first
112
+ elsif projects.size > 1
113
+ raise Informative, 'There are more than one Xcode project documents ' \
114
+ 'in the current working directory. Please specify ' \
115
+ 'which to use with the `--project` option.'
116
+ else
117
+ raise Informative, 'No Xcode project document found in the current ' \
118
+ 'working directory. Please specify which to use ' \
119
+ 'with the `--project` option.'
120
+ end
121
+ @xcodeproj_path = File.expand_path(xcodeproj_path)
122
+ end
123
+ @xcodeproj_path
124
+ end
125
+
126
+ def xcodeproj
127
+ @xcodeproj ||= Project.new(xcodeproj_path)
128
+ end
129
+ end
130
+ end
131
+
@@ -0,0 +1,53 @@
1
+ module Xcodeproj
2
+ class Command
3
+ class ProjectDiff < Command
4
+ def self.banner
5
+ %{Installing dependencies of a project:
6
+
7
+ $ project-diff PROJECT_1 PROJECT_2
8
+
9
+ Shows the difference between two projects in an UUID agnostic fashion.
10
+
11
+ To reduce the noise (and to simplify implementation) differences in the
12
+ other of arrays are ignored.
13
+ }
14
+ end
15
+
16
+ def self.options
17
+ [ ["--ignore KEY", "A key to ignore in the comparison. Can be specified multiple times."] ].concat(super)
18
+ end
19
+
20
+ def initialize(argv)
21
+ @path_project1 = argv.shift_argument
22
+ @path_project2 = argv.shift_argument
23
+ @keys_to_ignore = []
24
+ while (idx = argv.index('--ignore'))
25
+ @keys_to_ignore << argv.delete_at(idx + 1)
26
+ argv.delete_at(idx)
27
+ end
28
+ super unless argv.empty?
29
+ end
30
+
31
+
32
+ def run
33
+ hash_1 = Project.new(@path_project1).to_tree_hash
34
+ hash_2 = Project.new(@path_project2).to_tree_hash
35
+ (@keys_to_ignore).each do |key|
36
+ hash_1.recursive_delete(key)
37
+ hash_2.recursive_delete(key)
38
+ end
39
+
40
+ diff = hash_1.recursive_diff(hash_2, @path_project1, @path_project2)
41
+ diff.recursive_delete('displayName')
42
+
43
+ require 'yaml'
44
+ yaml = diff.to_yaml
45
+ yaml = yaml.gsub(@path_project1, @path_project1.cyan)
46
+ yaml = yaml.gsub(@path_project2, @path_project2.magenta)
47
+ puts yaml
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+
@@ -0,0 +1,35 @@
1
+ module Xcodeproj
2
+ class Command
3
+ class Show < Command
4
+ def self.banner
5
+ %{Installing dependencies of a project:
6
+
7
+ $ project-diff PROJECT_1 PROJECT_2
8
+
9
+ Shows a YAML reppresentation of a project.
10
+ }
11
+ end
12
+
13
+ def self.options
14
+ [
15
+ ["--project PATH", "The Xcode project document to use."],
16
+ ].concat(super)
17
+ end
18
+
19
+ def initialize(argv)
20
+ if argv.option('--project')
21
+ @xcodeproj_path = File.expand_path(argv.shift_argument)
22
+ end
23
+ super unless argv.empty?
24
+ end
25
+
26
+ def run
27
+ require 'yaml'
28
+ yaml = xcodeproj.to_tree_hash.to_yaml
29
+ puts yaml
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+
@@ -0,0 +1,43 @@
1
+ module Xcodeproj
2
+ class Command
3
+ class TargetDiff < Command
4
+ def self.banner
5
+ %{Installing dependencies of a project:
6
+
7
+ $ targets-diff [target 1] [target 2]
8
+
9
+ Shows the difference between two targets. (Only build source files atm.)
10
+ }
11
+ end
12
+
13
+ def self.options
14
+ [
15
+ ["--project PATH", "The Xcode project document to use."],
16
+ ].concat(super)
17
+ end
18
+
19
+ def initialize(argv)
20
+ @target1 = argv.shift_argument
21
+ @target2 = argv.shift_argument
22
+ if argv.option('--project')
23
+ @xcodeproj_path = File.expand_path(argv.shift_argument)
24
+ end
25
+ super unless argv.empty?
26
+ end
27
+
28
+ def run
29
+ require 'yaml'
30
+ differ = Helper::TargetDiff.new(xcodeproj, @target1, @target2)
31
+ files = differ.new_source_build_files.map do |build_file|
32
+ {
33
+ 'Name' => build_file.file_ref.name,
34
+ 'Path' => build_file.file_ref.path,
35
+ 'Build settings' => build_file.settings,
36
+ }
37
+ end
38
+ puts files.to_yaml
39
+ end
40
+ end
41
+ end
42
+ end
43
+
@@ -1,14 +1,41 @@
1
1
  module Xcodeproj
2
+
2
3
  # This class holds the data for a Xcode build settings file (xcconfig) and
3
4
  # serializes it.
5
+ #
4
6
  class Config
5
- # Returns a new instance of Config
6
- #
7
- # @param [Hash, File, String] xcconfig_hash_or_file Initial data.
7
+
8
8
  require 'set'
9
9
 
10
- attr_accessor :attributes, :frameworks, :weak_frameworks ,:libraries
10
+ # @return [Hash{String => String}] The attributes of the settings file
11
+ # excluding frameworks, weak_framework and libraries.
12
+ #
13
+ attr_accessor :attributes
14
+
15
+ # @return [Array<String>] The list of the frameworks required by this
16
+ # settings file.
17
+ #
18
+ attr_accessor :frameworks
11
19
 
20
+ # @return [Array<String>] The list of the *weak* frameworks required by
21
+ # this settings file.
22
+ #
23
+ attr_accessor :weak_frameworks
24
+
25
+ # @return [Array<String>] The list of the libraries required by this
26
+ # settings file.
27
+ #
28
+ attr_accessor :libraries
29
+
30
+ # @return [Array] The list of the configuration files included by this
31
+ # configuration file (`#include "SomeConfig"`).
32
+ #
33
+ attr_accessor :includes
34
+
35
+ # Returns a new instance of Config
36
+ #
37
+ # @param [Hash, File, String] xcconfig_hash_or_file Initial data.
38
+ #
12
39
  def initialize(xcconfig_hash_or_file = {})
13
40
  @attributes = {}
14
41
  @includes = []
@@ -16,7 +43,34 @@ module Xcodeproj
16
43
  merge!(extract_hash(xcconfig_hash_or_file))
17
44
  end
18
45
 
19
- # @return [Hash] The internal data.
46
+
47
+ #@! group Serialization
48
+
49
+ # Serializes the internal data in the xcconfig format.
50
+ #
51
+ # @example
52
+ #
53
+ # config = Config.new('PODS_ROOT' => '"$(SRCROOT)/Pods"', 'OTHER_LDFLAGS' => '-lxml2')
54
+ # config.to_s # => "PODS_ROOT = \"$(SRCROOT)/Pods\"\nOTHER_LDFLAGS = -lxml2"
55
+ #
56
+ # @return [String] The serialized internal data.
57
+ def to_s
58
+ to_hash.map { |key, value| "#{key} = #{value}" }.join("\n")
59
+ end
60
+
61
+ # @return [void] Writes the serialized representation of the internal data
62
+ # to the given path.
63
+ #
64
+ # @param [Pathname] pathname The file that the data should be written to.
65
+ #
66
+ def save_as(pathname)
67
+ pathname.open('w') { |file| file << to_s }
68
+ end
69
+
70
+ # @return [Hash] The hash reppresentation of the framework. The hash
71
+ # includes the frameworks, the weak frameworks and the libraries in the
72
+ # `Other Linker Flags` (`OTHER_LDFLAGS`).
73
+ #
20
74
  def to_hash
21
75
  hash = @attributes.dup
22
76
  flags = hash['OTHER_LDFLAGS'] || ''
@@ -29,23 +83,9 @@ module Xcodeproj
29
83
  hash
30
84
  end
31
85
 
32
- def ==(other)
33
- other.respond_to?(:to_hash) && other.to_hash == self.to_hash
34
- end
35
86
 
36
- # @return [Array] Config's include file list
37
- # @example
38
- #
39
- # Consider following xcconfig file:
40
- #
41
- # #include "SomeConfig"
42
- # Key1 = Value1
43
- # Key2 = Value2
44
- #
45
- # config.includes # => [ "SomeConfig" ]
46
- def includes
47
- @includes
48
- end
87
+
88
+ #@! group Merging
49
89
 
50
90
  # Merges the given xcconfig hash or Config into the internal data.
51
91
  #
@@ -59,6 +99,7 @@ module Xcodeproj
59
99
  # config.to_hash # => { 'PODS_ROOT' => '"$(SRCROOT)/Pods"', 'OTHER_LDFLAGS' => '-lxml2 -lz', 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers"' }
60
100
  #
61
101
  # @param [Hash, Config] xcconfig The data to merge into the internal data.
102
+ #
62
103
  def merge!(xcconfig)
63
104
  if xcconfig.is_a? Config
64
105
  @attributes.merge!(xcconfig.attributes) { |key, v1, v2| "#{v1} #{v2}" }
@@ -95,28 +136,15 @@ module Xcodeproj
95
136
  Xcodeproj::Config.new(self.to_hash.dup)
96
137
  end
97
138
 
98
- # Serializes the internal data in the xcconfig format.
99
- #
100
- # @example
101
- #
102
- # config = Config.new('PODS_ROOT' => '"$(SRCROOT)/Pods"', 'OTHER_LDFLAGS' => '-lxml2')
103
- # config.to_s # => "PODS_ROOT = \"$(SRCROOT)/Pods\"\nOTHER_LDFLAGS = -lxml2"
104
- #
105
- # @return [String] The serialized internal data.
106
- def to_s
107
- to_hash.map { |key, value| "#{key} = #{value}" }.join("\n")
108
- end
139
+
140
+ #@! group Object methods
109
141
 
110
142
  def inspect
111
143
  to_hash.inspect
112
144
  end
113
145
 
114
- # Writes the serialized representation of the internal data to the given
115
- # path.
116
- #
117
- # @param [Pathname] pathname The file that the data should be written to.
118
- def save_as(pathname)
119
- pathname.open('w') { |file| file << to_s }
146
+ def ==(other)
147
+ other.respond_to?(:to_hash) && other.to_hash == self.to_hash
120
148
  end
121
149
 
122
150
  private