cocoapods 0.16.4 → 0.17.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +108 -0
  3. data/README.md +3 -3
  4. data/bin/pod +1 -1
  5. data/lib/cocoapods.rb +31 -31
  6. data/lib/cocoapods/command.rb +62 -107
  7. data/lib/cocoapods/command/inter_process_communication.rb +103 -0
  8. data/lib/cocoapods/command/list.rb +45 -44
  9. data/lib/cocoapods/command/outdated.rb +28 -25
  10. data/lib/cocoapods/command/project.rb +90 -0
  11. data/lib/cocoapods/command/push.rb +50 -32
  12. data/lib/cocoapods/command/repo.rb +125 -155
  13. data/lib/cocoapods/command/search.rb +23 -12
  14. data/lib/cocoapods/command/setup.rb +103 -64
  15. data/lib/cocoapods/command/spec.rb +329 -90
  16. data/lib/cocoapods/config.rb +197 -44
  17. data/lib/cocoapods/downloader.rb +47 -34
  18. data/lib/cocoapods/executable.rb +98 -41
  19. data/lib/cocoapods/external_sources.rb +325 -0
  20. data/lib/cocoapods/file_list.rb +8 -1
  21. data/lib/cocoapods/gem_version.rb +7 -0
  22. data/lib/cocoapods/generator/acknowledgements.rb +71 -7
  23. data/lib/cocoapods/generator/acknowledgements/markdown.rb +10 -9
  24. data/lib/cocoapods/generator/acknowledgements/plist.rb +9 -8
  25. data/lib/cocoapods/generator/copy_resources_script.rb +2 -2
  26. data/lib/cocoapods/generator/documentation.rb +153 -37
  27. data/lib/cocoapods/generator/prefix_header.rb +82 -0
  28. data/lib/cocoapods/generator/target_header.rb +58 -0
  29. data/lib/cocoapods/generator/xcconfig.rb +130 -0
  30. data/lib/cocoapods/hooks/installer_representation.rb +123 -0
  31. data/lib/cocoapods/hooks/library_representation.rb +79 -0
  32. data/lib/cocoapods/hooks/pod_representation.rb +74 -0
  33. data/lib/cocoapods/installer.rb +398 -147
  34. data/lib/cocoapods/installer/analyzer.rb +556 -0
  35. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +253 -0
  36. data/lib/cocoapods/installer/file_references_installer.rb +179 -0
  37. data/lib/cocoapods/installer/pod_source_installer.rb +289 -0
  38. data/lib/cocoapods/installer/target_installer.rb +307 -112
  39. data/lib/cocoapods/installer/user_project_integrator.rb +140 -176
  40. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +193 -0
  41. data/lib/cocoapods/library.rb +195 -0
  42. data/lib/cocoapods/open_uri.rb +16 -14
  43. data/lib/cocoapods/project.rb +175 -52
  44. data/lib/cocoapods/resolver.rb +151 -164
  45. data/lib/cocoapods/sandbox.rb +276 -54
  46. data/lib/cocoapods/sandbox/file_accessor.rb +210 -0
  47. data/lib/cocoapods/sandbox/headers_store.rb +96 -0
  48. data/lib/cocoapods/sandbox/path_list.rb +178 -0
  49. data/lib/cocoapods/sources_manager.rb +218 -0
  50. data/lib/cocoapods/user_interface.rb +82 -18
  51. data/lib/cocoapods/{command → user_interface}/error_report.rb +5 -5
  52. data/lib/cocoapods/validator.rb +379 -0
  53. metadata +74 -55
  54. data/lib/cocoapods/command/install.rb +0 -55
  55. data/lib/cocoapods/command/linter.rb +0 -317
  56. data/lib/cocoapods/command/update.rb +0 -25
  57. data/lib/cocoapods/dependency.rb +0 -285
  58. data/lib/cocoapods/downloader/git.rb +0 -276
  59. data/lib/cocoapods/downloader/http.rb +0 -99
  60. data/lib/cocoapods/downloader/mercurial.rb +0 -26
  61. data/lib/cocoapods/downloader/subversion.rb +0 -42
  62. data/lib/cocoapods/local_pod.rb +0 -620
  63. data/lib/cocoapods/lockfile.rb +0 -274
  64. data/lib/cocoapods/platform.rb +0 -127
  65. data/lib/cocoapods/podfile.rb +0 -551
  66. data/lib/cocoapods/source.rb +0 -223
  67. data/lib/cocoapods/specification.rb +0 -579
  68. data/lib/cocoapods/specification/set.rb +0 -175
  69. data/lib/cocoapods/specification/statistics.rb +0 -112
  70. data/lib/cocoapods/user_interface/ui_pod.rb +0 -130
  71. data/lib/cocoapods/version.rb +0 -26
@@ -0,0 +1,210 @@
1
+ module Pod
2
+ class Sandbox
3
+
4
+ # Resolves the file patterns of a specification against its root directory,
5
+ # taking into account any exclude pattern and the default extensions to use
6
+ # for directories.
7
+ #
8
+ class FileAccessor
9
+
10
+ HEADER_EXTENSIONS = Xcodeproj::Constants::HEADER_FILES_EXTENSIONS
11
+
12
+ # @return [Sandbox::PathList] the directory where the source of the Pod
13
+ # is located.
14
+ #
15
+ attr_reader :path_list
16
+
17
+ # @return [Specification::Consumer] the consumer of the specification for
18
+ # which the file patterns should be resolved.
19
+ #
20
+ attr_reader :spec_consumer
21
+
22
+ # @param [Sandbox::PathList] path_list @see path_list
23
+ # @param [Specification::Consumer] spec_consumer @see spec_consumer
24
+ #
25
+ def initialize(path_list, spec_consumer)
26
+ @path_list = path_list
27
+ @spec_consumer = spec_consumer
28
+
29
+ unless @spec_consumer
30
+ raise Informative, "Attempt to initialize File Accessor without a specification consumer."
31
+ end
32
+ end
33
+
34
+ # @return [Specification] the specification.
35
+ #
36
+ def spec
37
+ spec_consumer.spec
38
+ end
39
+
40
+ # @return [Specification] the platform used to consume the specification.
41
+ #
42
+ def platform
43
+ spec_consumer.platform
44
+ end
45
+
46
+ # @return [String] A string suitable for debugging.
47
+ #
48
+ def inspect
49
+ "<#{self.class} spec=#{spec.name} platform=#{spec_consumer.platform} root=#{path_list.root}>"
50
+ end
51
+
52
+ #-----------------------------------------------------------------------#
53
+
54
+ public
55
+
56
+ # @!group Paths
57
+
58
+ # @return [Array<Pathname>] the source files of the specification.
59
+ #
60
+ def source_files
61
+ paths_for_attribute(:source_files)
62
+ end
63
+
64
+ # @return [Array<Pathname>] the headers of the specification.
65
+ #
66
+ def headers
67
+ extensions = HEADER_EXTENSIONS
68
+ source_files.select { |f| extensions.include?(f.extname) }
69
+ end
70
+
71
+ # @return [Array<Pathname>] the public headers of the specification.
72
+ #
73
+ def public_headers
74
+ public_headers = paths_for_attribute(:public_header_files)
75
+ if public_headers.nil? || public_headers.empty?
76
+ headers
77
+ else
78
+ public_headers
79
+ end
80
+ end
81
+
82
+ # @return [Hash{ Symbol => Array<Pathname> }] the resources of the
83
+ # specification grouped by destination.
84
+ #
85
+ def resources
86
+ options = {
87
+ :exclude_patterns => spec_consumer.exclude_files,
88
+ :include_dirs => true,
89
+ }
90
+ expanded_paths(spec_consumer.resources, options)
91
+ end
92
+
93
+ # @return [Array<Pathname>] the files of the specification to preserve.
94
+ #
95
+ def preserve_paths
96
+ paths_for_attribute(:preserve_paths)
97
+ end
98
+
99
+ # @return [Pathname] The of the prefix header file of the specification.
100
+ #
101
+ def prefix_header
102
+ if spec_consumer.prefix_header_file
103
+ path_list.root + spec_consumer.prefix_header_file
104
+ end
105
+ end
106
+
107
+ # @return [Pathname] The path of the auto-detected README file.
108
+ #
109
+ def readme
110
+ path_list.glob(%w[ readme{*,.*} ]).first
111
+ end
112
+
113
+ # @return [Pathname] The path of the license file as indicated in the
114
+ # specification or auto-detected.
115
+ #
116
+ def license
117
+ if spec_consumer.spec.root.license[:file]
118
+ path_list.root + spec_consumer.spec.root.license[:file]
119
+ else
120
+ path_list.glob(%w[ licen{c,s}e{*,.*} ]).first
121
+ end
122
+ end
123
+
124
+ #-----------------------------------------------------------------------#
125
+
126
+ private
127
+
128
+ # @!group Private helpers
129
+
130
+ # Returns the list of the paths founds in the file system for the
131
+ # attribute with given name. It takes into account any dir pattern and
132
+ # any file excluded in the specification.
133
+ #
134
+ # @param [Symbol] attribute
135
+ # the name of the attribute.
136
+ #
137
+ # @return [Array<Pathname>] the paths.
138
+ #
139
+ def paths_for_attribute(attribute)
140
+ file_patterns = spec_consumer.send(attribute)
141
+ options = {
142
+ :exclude_patterns => spec_consumer.exclude_files,
143
+ :dir_pattern => glob_for_attribute(attribute)
144
+ }
145
+ expanded_paths(file_patterns, options)
146
+ end
147
+
148
+ # Returns the pattern to use to glob a directory for an attribute.
149
+ #
150
+ # @param [Symbol] attribute
151
+ # the name of the attribute
152
+ #
153
+ # @return [String] the glob pattern.
154
+ #
155
+ # @todo Move to the cocoapods-core so it appears in the docs?
156
+ #
157
+ def glob_for_attribute(attrbute)
158
+ globs = {
159
+ :source_files => '*.{h,hpp,hh,m,mm,c,cpp}'.freeze,
160
+ :public_header_files => "*.{#{ HEADER_EXTENSIONS * ',' }}".freeze,
161
+ }
162
+ globs[attrbute]
163
+ end
164
+
165
+ # Matches the given patterns to the file present in the root of the path
166
+ # list.
167
+ #
168
+ # @param [Array<String, FileList>] patterns
169
+ # The patterns to expand.
170
+ #
171
+ # @param [String] dir_pattern
172
+ # The pattern to add to directories.
173
+ #
174
+ # @param [Array<String>] exclude_patterns
175
+ # The exclude patterns to pass to the PathList.
176
+ #
177
+ # @raise [Informative] If the pod does not exists.
178
+ #
179
+ # @return [Array<Pathname>] A list of the paths.
180
+ #
181
+ # @todo Implement case insensitive search
182
+ #
183
+ def expanded_paths(patterns, options = {})
184
+ return [] if patterns.empty?
185
+
186
+ file_lists = patterns.select { |p| p.is_a?(FileList) }
187
+ glob_patterns = patterns - file_lists
188
+
189
+ result = []
190
+ result << path_list.glob(glob_patterns, options)
191
+ result << file_lists.map do |file_list|
192
+ file_list.prepend_patterns(path_list.root)
193
+ file_list.glob
194
+ end
195
+
196
+ unless file_lists.empty?
197
+ # TODO Restore warning in 0.17 proper
198
+ # UI.warn "[#{spec_consumer.spec.name}] The usage of Rake FileList is deprecated. Use `exclude_files`."
199
+ end
200
+
201
+ result.flatten.compact.uniq
202
+ end
203
+
204
+ #-----------------------------------------------------------------------#
205
+
206
+ end
207
+ end
208
+ end
209
+
210
+
@@ -0,0 +1,96 @@
1
+ module Pod
2
+ class Sandbox
3
+
4
+ # Provides support for managing a header directory. It also keeps track of
5
+ # the header search paths.
6
+ #
7
+ class HeadersStore
8
+
9
+ # @return [Pathname] the absolute path of this header directory.
10
+ #
11
+ def root
12
+ @sandbox.root + @relative_path
13
+ end
14
+
15
+ # @return [Sandbox] the sandbox where this header directory is stored.
16
+ #
17
+ attr_reader :sandbox
18
+
19
+ # @param [Sandbox] @see sandbox
20
+ #
21
+ # @param [String] relative_path
22
+ # the relative path to the sandbox root and hence to the Pods
23
+ # project.
24
+ #
25
+ def initialize(sandbox, relative_path)
26
+ @sandbox = sandbox
27
+ @relative_path = relative_path
28
+ @search_paths = [relative_path]
29
+ end
30
+
31
+ # @return [Array<String>] All the search paths of the header directory in
32
+ # xcconfig format. The paths are specified relative to the pods
33
+ # root with the `${PODS_ROOT}` variable.
34
+ #
35
+ def search_paths
36
+ @search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" }
37
+ end
38
+
39
+ # Removes the directory as it is regenerated from scratch during each
40
+ # installation.
41
+ #
42
+ # @return [void]
43
+ #
44
+ def implode!
45
+ root.rmtree if root.exist?
46
+ end
47
+
48
+ #-----------------------------------------------------------------------#
49
+
50
+ public
51
+
52
+ # @!group Adding headers
53
+
54
+ # Adds a header to the directory.
55
+ #
56
+ # @param [Pathname] namespace_path
57
+ # the path where the header file should be stored relative to the
58
+ # headers directory.
59
+ #
60
+ # @param [Pathname] relative_header_path
61
+ # the path of the header file relative to the sandbox.
62
+ #
63
+ # @note This method adds the files to the search paths.
64
+ #
65
+ # @return [Pathname]
66
+ #
67
+ def add_files(namespace, relative_header_paths)
68
+ add_search_path(namespace)
69
+ namespaced_path = root + namespace
70
+ namespaced_path.mkpath unless File.exist?(namespaced_path)
71
+
72
+ relative_header_paths.map do |relative_header_path|
73
+ source = (@sandbox.root + relative_header_path).relative_path_from(namespaced_path)
74
+ Dir.chdir(namespaced_path) do
75
+ FileUtils.ln_sf(source, relative_header_path.basename)
76
+ end
77
+ namespaced_path + relative_header_path.basename
78
+ end
79
+ end
80
+
81
+ # Adds an header search path to the sandbox.
82
+ #
83
+ # @param [Pathname] path
84
+ # the path tho add.
85
+ #
86
+ # @return [void]
87
+ #
88
+ def add_search_path(path)
89
+ @search_paths << Pathname.new(@relative_path) + path
90
+ end
91
+
92
+ #-----------------------------------------------------------------------#
93
+
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,178 @@
1
+ module Pod
2
+ class Sandbox
3
+
4
+ # The PathList class is designed to perform multiple glob matches against
5
+ # a given directory. Basically, it generates a list of all the children
6
+ # paths and matches the globs patterns against them, resulting in just one
7
+ # access to the file system.
8
+ #
9
+ # @note A PathList once it has generated the list of the paths this is
10
+ # updated only if explicitly requested by calling
11
+ # {#read_file_system}
12
+ #
13
+ class PathList
14
+
15
+ # @return [Pathname] The root of the list whose files and directories
16
+ # are used to perform the matching operations.
17
+ #
18
+ attr_accessor :root
19
+
20
+ # @param [Pathname] root The root of the PathList.
21
+ #
22
+ def initialize(root)
23
+ @root = root
24
+ end
25
+
26
+ # @return [Array<String>] The list of absolute the path of all the files
27
+ # contained in {root}.
28
+ #
29
+ def files
30
+ read_file_system unless @files
31
+ @files
32
+ end
33
+
34
+ # @return [Array<String>] The list of absolute the path of all the
35
+ # directories contained in {root}.
36
+ #
37
+ def dirs
38
+ read_file_system unless @dirs
39
+ @dirs
40
+ end
41
+
42
+ # @return [void] Reads the file system and populates the files and paths
43
+ # lists.
44
+ #
45
+ def read_file_system
46
+ unless root.exist?
47
+ raise Informative, "Attempt to read non existent folder `#{root}`."
48
+ end
49
+ root_length = root.to_s.length+1
50
+ paths = Dir.glob(root + "**/*", File::FNM_DOTMATCH)
51
+ absolute_dirs = paths.select { |path| File.directory?(path) }
52
+ relative_dirs = absolute_dirs.map { |p| p[root_length..-1] }
53
+ absolute_paths = paths.reject { |p| p == "#{root}/." || p == "#{root}/.." }
54
+ relative_paths = absolute_paths.map { |p| p[root_length..-1] }
55
+ @files = relative_paths - relative_dirs
56
+ @dirs = relative_dirs.map { |d| d.gsub(/\/\.\.?$/,'') }.reject { |d| d == '.' || d == '..' } .uniq
57
+ end
58
+
59
+ #-----------------------------------------------------------------------#
60
+
61
+ public
62
+
63
+ # @!group Globbing
64
+
65
+ # @return [Array<Pathname>] Similar to {glob} but returns the absolute
66
+ # paths.
67
+ #
68
+ def glob(patterns, options = {})
69
+ relative_glob(patterns, options).map {|p| root + p }
70
+ end
71
+
72
+ # @return [Array<Pathname>] The list of relative paths that are case
73
+ # insensitively matched by a given pattern. This method emulates
74
+ # {Dir#glob} with the {File::FNM_CASEFOLD} option.
75
+ #
76
+ # @param [String,Array<String>] patterns
77
+ # A single {Dir#glob} like pattern, or a list of patterns.
78
+ #
79
+ # @param [String] dir_pattern
80
+ # An optional pattern to append to a pattern, if it is the path
81
+ # to a directory.
82
+ #
83
+ def relative_glob(patterns, options = {})
84
+ return [] if patterns.empty?
85
+
86
+ dir_pattern = options[:dir_pattern]
87
+ exclude_patterns = options[:exclude_patterns]
88
+ include_dirs = options[:include_dirs]
89
+
90
+ if include_dirs
91
+ full_list = files + dirs
92
+ else
93
+ full_list = files
94
+ end
95
+
96
+ list = Array(patterns).map do |pattern|
97
+ if pattern.is_a?(String)
98
+ pattern += '/' + dir_pattern if directory?(pattern) && dir_pattern
99
+ expanded_patterns = dir_glob_equivalent_patterns(pattern)
100
+ full_list.select do |path|
101
+ expanded_patterns.any? do |p|
102
+ File.fnmatch(p, path, File::FNM_CASEFOLD | File::FNM_PATHNAME)
103
+ end
104
+ end
105
+ else
106
+ full_list.select { |path| path.match(pattern) }
107
+ end
108
+ end.flatten
109
+
110
+ list = list.map { |path| Pathname.new(path) }
111
+ list -= relative_glob(exclude_patterns) if exclude_patterns
112
+ list
113
+ end
114
+
115
+ #-----------------------------------------------------------------------#
116
+
117
+ private
118
+
119
+ # @!group Private helpers
120
+
121
+ # @return [Bool] Wether a path is a directory. The result of this method
122
+ # computed without accessing the file system and is case
123
+ # insensitive.
124
+ #
125
+ # @param [String, Pathname] sub_path The path that could be a directory.
126
+ #
127
+ def directory?(sub_path)
128
+ sub_path = sub_path.to_s.downcase.sub(/\/$/, '')
129
+ dirs.any? { |dir| dir.downcase == sub_path }
130
+ end
131
+
132
+ # @return [Array<String>] An array of patterns converted from a
133
+ # {Dir.glob} pattern to patterns that {File.fnmatch} can handle.
134
+ # This is used by the {#relative_glob} method to emulate
135
+ # {Dir.glob}.
136
+ #
137
+ # The expansion provides support for:
138
+ #
139
+ # - Literals
140
+ #
141
+ # dir_glob_equivalent_patterns('{file1,file2}.{h,m}')
142
+ # => ["file1.h", "file1.m", "file2.h", "file2.m"]
143
+ #
144
+ # - Matching the direct children of a directory with `**`
145
+ #
146
+ # dir_glob_equivalent_patterns('Classes/**/file.m')
147
+ # => ["Classes/**/file.m", "Classes/file.m"]
148
+ #
149
+ # @param [String] pattern A {Dir#glob} like pattern.
150
+ #
151
+ def dir_glob_equivalent_patterns(pattern)
152
+ pattern = pattern.gsub('/**/', '{/**/,/}')
153
+ values_by_set = {}
154
+ pattern.scan(/\{[^}]*\}/) do |set|
155
+ values = set.gsub(/[{}]/, '').split(',')
156
+ values_by_set[set] = values
157
+ end
158
+
159
+ if values_by_set.empty?
160
+ [ pattern ]
161
+ else
162
+ patterns = [ pattern ]
163
+ values_by_set.each do |set, values|
164
+ patterns = patterns.map do |old_pattern|
165
+ values.map do |value|
166
+ old_pattern.gsub(set, value)
167
+ end
168
+ end.flatten
169
+ end
170
+ patterns
171
+ end
172
+ end
173
+
174
+ #-----------------------------------------------------------------------#
175
+
176
+ end
177
+ end
178
+ end