Skip to content

Commit b19f9d0

Browse files
committed
add SingleSource - a source that is actually a pod repo
1 parent 81e2b03 commit b19f9d0

File tree

3 files changed

+200
-0
lines changed

3 files changed

+200
-0
lines changed

lib/cocoapods-core.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class Informative < PlainInformative; end
2828
autoload :Podfile, 'cocoapods-core/podfile'
2929
autoload :Source, 'cocoapods-core/source'
3030
autoload :CDNSource, 'cocoapods-core/cdn_source'
31+
autoload :SingleSource, 'cocoapods-core/single_source'
3132
autoload :TrunkSource, 'cocoapods-core/trunk_source'
3233
autoload :Specification, 'cocoapods-core/specification'
3334
autoload :StandardError, 'cocoapods-core/standard_error'
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
require 'cocoapods-core/source/acceptor'
2+
require 'cocoapods-core/source/aggregate'
3+
require 'cocoapods-core/source/health_reporter'
4+
require 'cocoapods-core/source/manager'
5+
require 'cocoapods-core/source/metadata'
6+
7+
module Pod
8+
# The Source class is responsible to manage a collection of podspecs.
9+
#
10+
# The backing store of the podspecs collection is an implementation detail
11+
# abstracted from the rest of CocoaPods.
12+
#
13+
# The default implementation uses a git repo as a backing store, where the
14+
# podspecs are namespaced as:
15+
#
16+
# "#{SPEC_NAME}/#{VERSION}/#{SPEC_NAME}.podspec"
17+
#
18+
class SingleSource < Source
19+
# @param [Pathname, String] repo @see #repo.
20+
#
21+
def initialize(repo)
22+
super(repo)
23+
spec_paths
24+
end
25+
26+
private
27+
28+
def raw_versions
29+
@version_tags ||= repo_git(%w(tag)).split(/\s+/).map do |v|
30+
version = Version.new(v)
31+
rescue ArgumentError
32+
end.compact
33+
end
34+
35+
def process_podspec(path, output_path)
36+
spec = Specification.from_file(path)
37+
File.open(output_path, 'w') { |f| f.write(spec.to_pretty_json) }
38+
output_path
39+
end
40+
41+
def preload_podspecs_at_version(version)
42+
version_dir = repo.join('.git', '.specs', version.to_s)
43+
if version_dir.exist?
44+
Pathname.glob(version_dir.join('*'))
45+
else
46+
repo_git(['checkout', version.to_s])
47+
version_dir.mkpath
48+
Pathname.glob(repo.join('*.podspec')).map do |podspec_path|
49+
name = podspec_path.basename('.podspec')
50+
process_podspec(podspec_path, version_dir.join("#{name}.podspec.json"))
51+
end.compact
52+
end
53+
end
54+
55+
def spec_paths
56+
raw_versions.map do |version|
57+
preload_podspecs_at_version(version)
58+
end.flatten
59+
end
60+
61+
public
62+
63+
# @!group Querying the source
64+
#-------------------------------------------------------------------------#
65+
66+
# @return [Array<String>] the list of the name of all the Pods.
67+
#
68+
#
69+
def pods
70+
spec_paths.map do |spec_path|
71+
spec_path.basename('.podspec.json').to_s
72+
end.flatten.uniq.sort
73+
end
74+
75+
# @return [Array<Version>] all the available versions for the Pod, sorted
76+
# from highest to lowest.
77+
#
78+
# @param [String] name
79+
# the name of the Pod.
80+
#
81+
def versions(name)
82+
return nil unless pods.include?(name)
83+
@versions_by_name[name] ||= raw_versions.map do |version|
84+
if specification_path(name, version)
85+
version
86+
else
87+
nil
88+
end
89+
end.compact.sort.reverse
90+
end
91+
92+
# Returns the path of the specification with the given name and version.
93+
#
94+
# @param [String] name
95+
# the name of the Pod.
96+
#
97+
# @param [Version,String] version
98+
# the version for the specification.
99+
#
100+
# @return [Pathname] The path of the specification.
101+
#
102+
def specification_path(name, version)
103+
raise ArgumentError, 'No name' unless name
104+
raise ArgumentError, 'No version' unless version
105+
106+
preload_podspecs_at_version(version)
107+
108+
path = repo.join('.git', '.specs', version.to_s, "#{name}.podspec.json")
109+
110+
return nil unless path.exist?
111+
112+
path
113+
end
114+
115+
# @return [Array<Specification>] all the specifications contained by the
116+
# source.
117+
#
118+
def all_specs
119+
specs = spec_paths.map do |path|
120+
begin
121+
Specification.from_file(path)
122+
rescue
123+
CoreUI.warn "Skipping `#{path.relative_path_from(repo)}` because the " \
124+
'podspec contains errors.'
125+
next
126+
end
127+
end
128+
specs.compact
129+
end
130+
131+
132+
# @!group Searching the source
133+
#-------------------------------------------------------------------------#
134+
135+
# @return [Set] a set for a given dependency. The set is identified by the
136+
# name of the dependency and takes into account subspecs.
137+
#
138+
# @note This method is optimized for fast lookups by name, i.e. it does
139+
# *not* require iterating through {#pod_sets}
140+
#
141+
# @todo Rename to #load_set
142+
#
143+
def search(query)
144+
if query.is_a?(Dependency)
145+
query = query.root_name
146+
end
147+
148+
if (versions = versions(query)) && !versions.empty?
149+
set = set(query)
150+
return set if set.specification_name == query
151+
end
152+
end
153+
154+
# @return [Array<Set>] The list of the sets that contain the search term.
155+
#
156+
# @param [String] query
157+
# the search term. Can be a regular expression.
158+
#
159+
# @param [Bool] full_text_search
160+
# whether the search should be limited to the name of the Pod or
161+
# should include also the author, the summary, and the description.
162+
#
163+
# @note full text search requires to load the specification for each pod,
164+
# hence is considerably slower.
165+
#
166+
# @todo Rename to #search
167+
#
168+
def search_by_name(query, full_text_search = false)
169+
regexp_query = /#{query}/i
170+
171+
names = pods.grep(regexp_query)
172+
names.map { |pod_name| set(pod_name) }
173+
end
174+
175+
# @!group Updating the source
176+
#-------------------------------------------------------------------------#
177+
178+
# Updates the local clone of the source repo.
179+
#
180+
# @param [Bool] show_output
181+
#
182+
# @return [Array<String>] changed_spec_paths
183+
# Returns the list of changed spec paths.
184+
#
185+
def update(show_output)
186+
result = super(show_output)
187+
repo.join('.git', '.specs').rmtree if repo.join('.git', '.specs').exist?
188+
all_specs
189+
result
190+
end
191+
192+
def verify_compatibility!
193+
end
194+
195+
end
196+
end

lib/cocoapods-core/source/manager.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,10 @@ def source_from_path(path)
315315
TrunkSource.new(key)
316316
when (key + '.url').exist?
317317
CDNSource.new(key)
318+
when key.join('.git', '.specs').exist? || Dir[key.join('*.podspec')].count > 0
319+
SingleSource.new(key)
318320
else
321+
require 'pry'; binding.pry
319322
Source.new(key)
320323
end
321324
end

0 commit comments

Comments
 (0)