Skip to content

Commit 019d4c5

Browse files
author
Soumya Mahunt
committed
feat: add all remotes supported by cocoapods-downloader
1 parent 5e97145 commit 019d4c5

File tree

12 files changed

+384
-112
lines changed

12 files changed

+384
-112
lines changed

Gemfile.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ PATH
22
remote: .
33
specs:
44
cocoapods-embed-flutter (0.0.1)
5+
cocoapods
6+
fileutils
57
yaml
68

79
GEM
@@ -66,6 +68,7 @@ GEM
6668
ethon (0.15.0)
6769
ffi (>= 1.15.0)
6870
ffi (1.15.5)
71+
fileutils (1.6.0)
6972
fourflusher (2.3.1)
7073
fuzzy_match (2.0.4)
7174
gh_inspector (1.1.3)

cocoapods-embed-flutter.gemspec

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Gem::Specification.new do |spec|
1919
spec.require_paths = ['lib']
2020

2121
spec.add_dependency 'yaml'
22+
spec.add_dependency 'fileutils'
23+
spec.add_dependency 'cocoapods'
2224

2325
spec.add_development_dependency 'bundler'
2426
spec.add_development_dependency 'rake'

example/ios_app/Gemfile.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ PATH
22
remote: ../..
33
specs:
44
cocoapods-embed-flutter (0.0.1)
5+
cocoapods
6+
fileutils
57
yaml
68

79
GEM
@@ -65,6 +67,7 @@ GEM
6567
ethon (0.15.0)
6668
ffi (>= 1.15.0)
6769
ffi (1.15.5)
70+
fileutils (1.1.0)
6871
fourflusher (2.3.1)
6972
fuzzy_match (2.0.4)
7073
gh_inspector (1.1.3)

example/ios_app/Podfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ target 'ios_app' do
77
use_frameworks!
88

99
# Pods for ios_app
10-
flutter_module 'flutter_module', :path => '../'
10+
pub 'flutter_module', :path => '../'
1111
end

example/ios_app/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ SPEC CHECKSUMS:
2323
flutter_module: d1e1ff44505640bd9aa37f23f63380c646272be4
2424
FlutterPluginRegistrant: 2afd5ea46d3a949472c9b7da6462d8fbf7d8b16e
2525

26-
PODFILE CHECKSUM: c3b3a9549c635bdd7321f4b209b67310a97803e9
26+
PODFILE CHECKSUM: 63b6421f4bf00554065d89d2308ed2deb78332fc
2727

2828
COCOAPODS: 1.11.2
Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,42 @@
11
require 'cocoapods-embed-flutter/flutter/pubspec'
22

33
module Flutter
4-
class Dependency
5-
attr_reader :name, :requirements, :parent_spec, :is_dev_dependency
4+
module Pub
5+
class Dependency
6+
attr_reader :name, :requirements, :parent_spec, :is_dev_dependency
67

7-
def initialize(name, requirements, parent_spec, dev_dependency = false)
8-
raise StandardError, 'A flutter dependency requires a name.' unless name
9-
raise StandardError, 'A flutter dependency requires a parent pubspec.' unless parent_spec.is_a?(Flutter::PubSpec)
10-
@name = name
11-
@requirements = requirements
12-
@parent_spec = parent_spec
13-
@is_dev_dependency = dev_dependency
14-
end
8+
def initialize(name, requirements, parent_spec, dev_dependency = false)
9+
raise StandardError, 'A flutter dependency requires a name.' unless name
10+
raise StandardError, 'A flutter dependency requires a parent pubspec.' unless parent_spec.is_a?(Flutter::Pub::Spec)
11+
@name = name
12+
@requirements = requirements
13+
@parent_spec = parent_spec
14+
@is_dev_dependency = dev_dependency
15+
end
1516

16-
def self.create_from_hash(hash, parent_spec, dev_dependency = false)
17-
raise StandardError, 'A flutter dependency requires a parent pubspec.' unless parent_spec.is_a?(Flutter::PubSpec)
18-
hash.keys.map { |key| Flutter::Dependency.new(key, hash[key], parent_spec, dev_dependency) }
19-
end
17+
def self.create_from_hash(hash, parent_spec, dev_dependency = false)
18+
raise StandardError, 'A flutter dependency requires a parent pubspec.' unless parent_spec.is_a?(Flutter::Pub::Spec)
19+
hash.keys.map { |key| Dependency.new(key, hash[key], parent_spec, dev_dependency) }
20+
end
2021

21-
def is_local
22-
requirements.is_a?(Hash) && requirements.include?('path')
23-
end
22+
def local?
23+
requirements.is_a?(Hash) && requirements.include?('path')
24+
end
2425

25-
def spec
26-
Flutter::PubSpec.new(File.expand_path(path, File.dirname(parent_spec.file_path)))
27-
end
26+
def spec
27+
Spec.find(name, File.expand_path(path, File.dirname(parent_spec.defined_in_file)))
28+
end
2829

29-
def install
30-
spec.setup if is_local
31-
end
30+
def install
31+
spec.setup if local?
32+
end
3233

33-
def method_missing(m, *args, &block)
34-
if requirements.is_a?(Hash) && requirements.include?(m.to_s)
35-
return requirements[m.to_s]
34+
def method_missing(m, *args, &block)
35+
if requirements.is_a?(Hash) && requirements.include?(m.to_s)
36+
return requirements[m.to_s]
37+
end
38+
super.method_missing(m, *args, &block)
3639
end
37-
super.method_missing(m, *args, &block)
3840
end
3941
end
4042
end
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
require 'cocoapods'
2+
require 'fileutils'
3+
4+
module Flutter
5+
module Pub
6+
module Downloader
7+
# Downloads a package from the given `request` to the given `target` location.
8+
#
9+
# @return [Response] The download response for this download.
10+
#
11+
# @param [Request] request
12+
# the request that describes this pod download.
13+
#
14+
# @param [Pathname,Nil] target
15+
# the location to which this pod should be downloaded. If `nil`,
16+
# then the pod will only be cached.
17+
#
18+
# @param [Boolean] can_cache
19+
# whether caching is allowed.
20+
#
21+
# @param [Pathname,Nil] cache_path
22+
# the path used to cache pod downloads.
23+
#
24+
def self.download(
25+
request,
26+
target,
27+
can_cache: true,
28+
cache_path: Pod::Config.instance.cache_root + 'Pods'
29+
)
30+
can_cache &&= !Pod::Config.instance.skip_download_cache
31+
32+
request = Pod::Downloader.preprocess_request(request)
33+
34+
# if can_cache
35+
# raise ArgumentError, 'Must provide a `cache_path` when caching.' unless cache_path
36+
# cache = Pod::Downloader::Cache.new(cache_path)
37+
# result = cache.download_pod(request)
38+
# else
39+
# raise ArgumentError, 'Must provide a `target` when caching is disabled.' unless target
40+
41+
# result, = Pod::Downloader.download_request(request, target)
42+
# Pod::Installer::PodSourcePreparer.new(result.spec, result.location).prepare!
43+
# end
44+
raise ArgumentError, 'Must provide a `target` when caching is disabled.' unless target
45+
result, = Pod::Downloader.download_request(request, target)
46+
47+
if target && result.location && target != result.location
48+
Pod::UI.message "Copying #{request.name} from `#{result.location}` to #{UI.path target}", '> ' do
49+
Pod::Downloader::Cache.read_lock(result.location) do
50+
FileUtils.rm_rf target
51+
FileUtils.cp_r(result.location, target)
52+
end
53+
end
54+
end
55+
result
56+
end
57+
end
58+
end
59+
end
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
# Similar to:
2+
# https://github.com/CocoaPods/CocoaPods/blob/master/lib/cocoapods/external_sources/abstract_external_source.rb
3+
require 'cocoapods-embed-flutter/flutter/downloader'
4+
require 'cocoapods'
5+
6+
module Flutter
7+
module Pub
8+
module ExternalSources
9+
SOURCE_KEYS = {
10+
:git => [:tag, :branch, :commit, :submodules].freeze,
11+
:svn => [:folder, :tag, :revision].freeze,
12+
:hg => [:revision].freeze,
13+
:http => [:flatten, :type, :sha256, :sha1, :headers].freeze,
14+
}.freeze
15+
16+
def self.fetchWithNameAndOptions(name, options)
17+
raise StandardError, 'A flutter module requires a name.' unless name
18+
19+
options = options.last if options.is_a?(Array)
20+
raise StandardError, "No options specified for flutter module: '#{name}'." unless options.is_a?(Hash)
21+
22+
if options.key?(:path)
23+
path = options[:path]
24+
elsif SOURCE_KEYS.keys.any? { |key| options.key?(key) }
25+
source = DownloaderSource.new(name, options, Pod::Config.instance.podfile_path)
26+
source.fetch(Pod::Config.instance.sandbox)
27+
path = source.normalized_pupspec_path
28+
else
29+
raise StandardError, "Invalid flutter module: '#{name}'."
30+
end
31+
32+
return Spec.find(name, path)
33+
end
34+
35+
# Provides support for fetching a specification file from a source handled
36+
# by the downloader. Supports all the options of the downloader
37+
#
38+
# @note The pubspec must be in the root of the repository
39+
# or in directory with the name provided
40+
#
41+
class DownloaderSource
42+
# @return [String] the name of the Package described by this external source.
43+
#
44+
attr_reader :name
45+
46+
# @return [Hash{Symbol => String}] the hash representation of the
47+
# external source.
48+
#
49+
attr_reader :params
50+
51+
# @return [String] the path where the podfile is defined to resolve
52+
# relative paths.
53+
#
54+
attr_reader :podfile_path
55+
56+
# @return [Boolean] Whether the source is allowed to touch the cache.
57+
#
58+
attr_reader :can_cache
59+
alias_method :can_cache?, :can_cache
60+
61+
# Initialize a new instance
62+
#
63+
# @param [String] name @see #name
64+
# @param [Hash] params @see #params
65+
# @param [String] podfile_path @see #podfile_path
66+
# @param [Boolean] can_cache @see #can_cache
67+
#
68+
def initialize(name, params, podfile_path, can_cache = true)
69+
@name = name
70+
@params = params
71+
@podfile_path = podfile_path
72+
@can_cache = can_cache
73+
end
74+
75+
# @return [Boolean] whether an external source source is equal to another
76+
# according to the {#name} and to the {#params}.
77+
#
78+
def ==(other)
79+
return false if other.nil?
80+
name == other.name && params == other.params
81+
end
82+
83+
84+
public
85+
86+
# @!group Subclasses hooks
87+
88+
# Fetches the external source from the remote according to the params.
89+
#
90+
# @param [Sandbox] sandbox
91+
# the sandbox where the specification should be stored.
92+
#
93+
# @return [void]
94+
#
95+
def fetch(sandbox)
96+
pre_download(sandbox)
97+
end
98+
99+
# @return [String] a string representation of the source suitable for UI.
100+
#
101+
def description
102+
strategy = Pod::Downloader.strategy_from_options(params)
103+
options = params.dup
104+
url = options.delete(strategy)
105+
result = "from `#{url}`"
106+
options.each do |key, value|
107+
result << ", #{key} `#{value}`"
108+
end
109+
result
110+
end
111+
112+
# Return the normalized path for a pubspec for a relative declared path.
113+
#
114+
# @param [String] declared_path
115+
# The path declared in the podfile.
116+
#
117+
# @return [String] The uri of the pubspec appending the name of the file
118+
# and expanding it if necessary.
119+
#
120+
# @note If the declared path is expanded only if the represents a path
121+
# relative to the file system.
122+
#
123+
def normalized_pupspec_path(declared_path)
124+
Spec.find_file(name, declared_path)
125+
end
126+
127+
def normalized_pupspec_path
128+
Spec.find_file(name, target)
129+
end
130+
131+
private
132+
133+
# @! Subclasses helpers
134+
135+
# Pre-downloads a Pod passing the options to the downloader and informing
136+
# the sandbox.
137+
#
138+
# @param [Sandbox] sandbox
139+
# The sandbox where the Pod should be downloaded.
140+
#
141+
# @note To prevent a double download of the repository the pod is
142+
# marked as pre-downloaded indicating to the installer that only
143+
# clean operations are needed.
144+
#
145+
# @todo The downloader configuration is the same of the
146+
# #{PodSourceInstaller} and it needs to be kept in sync.
147+
#
148+
# @return [void]
149+
#
150+
def pre_download(sandbox)
151+
title = "Pre-downloading: `#{name}` #{description}"
152+
Pod::UI.titled_section(title, :verbose_prefix => '-> ') do
153+
begin
154+
download_result = Downloader.download(download_request, target, :can_cache => can_cache)
155+
rescue Pod::DSLError => e
156+
raise Pod::Informative, "Failed to load '#{name}' pubspec: #{e.message}"
157+
rescue => e
158+
raise Pod::Informative, "Failed to download '#{name}': #{e.message}"
159+
end
160+
161+
# spec = download_result.spec
162+
# raise Pod::Informative, "Unable to find a specification for '#{name}'." unless spec
163+
164+
# since the podspec might be cleaned, we want the checksum to refer
165+
# to the json in the sandbox
166+
# spec.defined_in_file = nil
167+
168+
# store_podspec(sandbox, spec)
169+
# sandbox.store_pre_downloaded_pod(name)
170+
# sandbox.store_checkout_source(name, download_result.checkout_options)
171+
end
172+
end
173+
174+
def download_request
175+
Pod::Downloader::Request.new(
176+
:name => name,
177+
:params => params,
178+
)
179+
end
180+
181+
def target
182+
return Pod::Config.instance.sandbox.pod_dir(name)
183+
end
184+
end
185+
end
186+
end
187+
end

0 commit comments

Comments
 (0)