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